canvas-datagrid 0.3.25 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/dist/canvas-datagrid.debug.js +2913 -116
- package/dist/canvas-datagrid.debug.map +1 -1
- package/dist/canvas-datagrid.js +1 -1
- package/dist/canvas-datagrid.module.js +1 -1
- package/dist/canvas-datagrid.module.js.map +1 -1
- package/dist/types.d.ts +141 -0
- package/lib/contextMenu.js +427 -10
- package/lib/defaults.js +44 -0
- package/lib/docs.js +18 -0
- package/lib/dom.js +18 -1
- package/lib/draw.js +866 -36
- package/lib/events/index.js +224 -36
- package/lib/events/util.js +1 -1
- package/lib/groups/util.js +42 -0
- package/lib/intf.js +610 -1
- package/lib/publicMethods.js +459 -4
- package/package.json +1 -1
package/lib/contextMenu.js
CHANGED
|
@@ -538,8 +538,114 @@ export default function (self) {
|
|
|
538
538
|
});
|
|
539
539
|
}
|
|
540
540
|
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Return a tuple if the user selected contiguous columns, otherwise `null`.
|
|
544
|
+
* Info: Because the user may reorder the columns,
|
|
545
|
+
* the schemaIndex of the first item may be greater than the schemaIndex of the second item,
|
|
546
|
+
* but the columnIndex of the firs item must less than the columnIndex of the second item.
|
|
547
|
+
* @param {any[]} schema from `self.getSchema()`
|
|
548
|
+
* @returns {any[]} column schemas tuple (each schema has an additional field `schemaIndex`)
|
|
549
|
+
*/
|
|
550
|
+
function getSelectedContiguousColumns(ev, schema) {
|
|
551
|
+
const memoKey = '__contiguousColumns';
|
|
552
|
+
if (Array.isArray(ev[memoKey]) || ev[memoKey] === null) return ev[memoKey];
|
|
553
|
+
ev[memoKey] = null;
|
|
554
|
+
|
|
555
|
+
if (!Array.isArray(self.selections) || self.selections.length === 0) return;
|
|
556
|
+
const selection = self.selections[0];
|
|
557
|
+
if (!selection || selection.length === 0) return;
|
|
558
|
+
for (let rowIndex = 0; rowIndex < self.viewData.length; rowIndex++) {
|
|
559
|
+
const row = self.viewData[rowIndex];
|
|
560
|
+
if (!row) continue;
|
|
561
|
+
const compare = self.selections[rowIndex];
|
|
562
|
+
if (!compare) return;
|
|
563
|
+
if (compare.length !== selection.length) return;
|
|
564
|
+
for (let i = 0; i < selection.length; i++)
|
|
565
|
+
if (selection[i] !== compare[i]) return;
|
|
566
|
+
}
|
|
567
|
+
selection.sort((a, b) => a - b);
|
|
568
|
+
|
|
569
|
+
/** @type {number[][]} */
|
|
570
|
+
const ranges = [];
|
|
571
|
+
let begin = selection[0];
|
|
572
|
+
let end = selection[0];
|
|
573
|
+
for (let i = 1; i < selection.length; i++) {
|
|
574
|
+
const orderIndex = selection[i];
|
|
575
|
+
if (orderIndex === end + 1) {
|
|
576
|
+
end = orderIndex;
|
|
577
|
+
continue;
|
|
578
|
+
}
|
|
579
|
+
ranges.push([begin, end]);
|
|
580
|
+
begin = orderIndex;
|
|
581
|
+
end = orderIndex;
|
|
582
|
+
}
|
|
583
|
+
ranges.push([begin, end]);
|
|
584
|
+
|
|
585
|
+
const currentOrderIndex = ev.cell.columnIndex;
|
|
586
|
+
const matchedRange = ranges.find(
|
|
587
|
+
(range) =>
|
|
588
|
+
currentOrderIndex >= range[0] &&
|
|
589
|
+
currentOrderIndex <= range[1] &&
|
|
590
|
+
range[0] !== range[1],
|
|
591
|
+
);
|
|
592
|
+
if (!matchedRange) return;
|
|
593
|
+
|
|
594
|
+
/** @type {number[]} orders[index] => columnIndex */
|
|
595
|
+
const orders = self.orders.columns;
|
|
596
|
+
if (!Array.isArray(orders)) return;
|
|
597
|
+
|
|
598
|
+
const matchedSchema = matchedRange.map((orderIndex) => {
|
|
599
|
+
const schemaIndex = orders[orderIndex];
|
|
600
|
+
const thisSchema = schema[schemaIndex];
|
|
601
|
+
return Object.assign({}, thisSchema, { orderIndex });
|
|
602
|
+
});
|
|
603
|
+
if (matchedSchema.findIndex((it) => !it) >= 0) return;
|
|
604
|
+
return (ev[memoKey] = matchedSchema);
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* @param {boolean} [allowOnlyOneRow]
|
|
608
|
+
* @returns {number[]} a rowIndex tuple. It can contains one row index or two row indexes.
|
|
609
|
+
*/
|
|
610
|
+
function getSelectedContiguousRows(allowOnlyOneRow) {
|
|
611
|
+
let range = [];
|
|
612
|
+
let prev = -2;
|
|
613
|
+
let ok = true;
|
|
614
|
+
self.selections.forEach(function (row, index) {
|
|
615
|
+
if (!ok) return;
|
|
616
|
+
if (prev < -1) {
|
|
617
|
+
prev = index;
|
|
618
|
+
range[0] = index;
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
if (index !== prev + 1 || !row || row.length === 0) {
|
|
622
|
+
ok = false;
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
prev = index;
|
|
626
|
+
range[1] = index;
|
|
627
|
+
});
|
|
628
|
+
if (ok) {
|
|
629
|
+
if (range.length === 1) return allowOnlyOneRow ? range : null;
|
|
630
|
+
return range;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
541
633
|
function addDefaultContextMenuItem(e) {
|
|
542
|
-
|
|
634
|
+
const schema = self.getSchema();
|
|
635
|
+
/**
|
|
636
|
+
* A map between columnIndex and column data
|
|
637
|
+
* @type {Map<string,any>}
|
|
638
|
+
*/
|
|
639
|
+
let columns;
|
|
640
|
+
const getColumnsMap = () => {
|
|
641
|
+
if (!columns)
|
|
642
|
+
columns = new Map(schema.map((_col) => [_col.columnIndex, _col]));
|
|
643
|
+
return columns;
|
|
644
|
+
};
|
|
645
|
+
const isSorting =
|
|
646
|
+
self.orderings.columns && self.orderings.columns.length > 0;
|
|
647
|
+
|
|
648
|
+
const isNormalCell =
|
|
543
649
|
!(
|
|
544
650
|
e.cell.isBackground ||
|
|
545
651
|
e.cell.isColumnHeaderCellCap ||
|
|
@@ -609,20 +715,35 @@ export default function (self) {
|
|
|
609
715
|
},
|
|
610
716
|
});
|
|
611
717
|
if (e.cell && e.cell.header && e.cell.columnIndex > -1) {
|
|
718
|
+
// This variable represents the order index because of the following codes from `draw.js`:
|
|
719
|
+
// columnIndex: columnOrderIndex,
|
|
720
|
+
const columnOrderIndex = e.cell.columnIndex;
|
|
721
|
+
const columnIndex = self.orders.columns[columnOrderIndex];
|
|
722
|
+
|
|
723
|
+
const contiguousColumns = getSelectedContiguousColumns(e, schema);
|
|
724
|
+
let title = '';
|
|
725
|
+
if (contiguousColumns) {
|
|
726
|
+
title = contiguousColumns
|
|
727
|
+
.map((col) => col.title || col.name)
|
|
728
|
+
.join('-');
|
|
729
|
+
} else {
|
|
730
|
+
const column = schema[columnIndex];
|
|
731
|
+
if (column) title = column.title || column.name;
|
|
732
|
+
}
|
|
612
733
|
e.items.push({
|
|
613
|
-
title: self.attributes.hideColumnText.replace(
|
|
614
|
-
/%s/gi,
|
|
615
|
-
e.cell.header.title || e.cell.header.name,
|
|
616
|
-
),
|
|
734
|
+
title: self.attributes.hideColumnText.replace(/%s/gi, title),
|
|
617
735
|
click: function (ev) {
|
|
618
|
-
self.getSchema()[e.cell.columnIndex].hidden = true;
|
|
619
736
|
ev.preventDefault();
|
|
620
737
|
self.stopPropagation(ev);
|
|
621
738
|
self.disposeContextMenu();
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
739
|
+
if (contiguousColumns) {
|
|
740
|
+
self.hideColumns(
|
|
741
|
+
contiguousColumns[0].orderIndex,
|
|
742
|
+
contiguousColumns[1].orderIndex,
|
|
743
|
+
);
|
|
744
|
+
} else {
|
|
745
|
+
self.hideColumns(columnOrderIndex);
|
|
746
|
+
}
|
|
626
747
|
},
|
|
627
748
|
});
|
|
628
749
|
}
|
|
@@ -684,6 +805,254 @@ export default function (self) {
|
|
|
684
805
|
},
|
|
685
806
|
});
|
|
686
807
|
}
|
|
808
|
+
|
|
809
|
+
//#region hide rows
|
|
810
|
+
const canHideRows = !isSorting && e.cell.isRowHeader && e.cell.header;
|
|
811
|
+
if (canHideRows) {
|
|
812
|
+
const range = getSelectedContiguousRows(true);
|
|
813
|
+
if (range) {
|
|
814
|
+
const boundRowIndexes = range.map((viewRowIndex) =>
|
|
815
|
+
self.getBoundRowIndexFromViewRowIndex(viewRowIndex),
|
|
816
|
+
);
|
|
817
|
+
let title;
|
|
818
|
+
if (boundRowIndexes.length === 1) {
|
|
819
|
+
if (typeof boundRowIndexes[0] === 'number')
|
|
820
|
+
title = boundRowIndexes[0] + 1;
|
|
821
|
+
else title = range[0] + 1;
|
|
822
|
+
|
|
823
|
+
title = self.attributes.showHideRow.replace('%s', title);
|
|
824
|
+
// hide one row
|
|
825
|
+
e.items.push({
|
|
826
|
+
title,
|
|
827
|
+
click: function (ev) {
|
|
828
|
+
ev.preventDefault();
|
|
829
|
+
self.hideRows(boundRowIndexes[0], boundRowIndexes[0]);
|
|
830
|
+
},
|
|
831
|
+
});
|
|
832
|
+
} else if (boundRowIndexes[0] <= boundRowIndexes[1]) {
|
|
833
|
+
title = boundRowIndexes
|
|
834
|
+
.map((it, index) => {
|
|
835
|
+
if (typeof it === 'number') return it + 1;
|
|
836
|
+
return range[index] + 1;
|
|
837
|
+
})
|
|
838
|
+
.join('-');
|
|
839
|
+
title = self.attributes.showHideRows.replace('%s', title);
|
|
840
|
+
// hide rows
|
|
841
|
+
e.items.push({
|
|
842
|
+
title,
|
|
843
|
+
click: function (ev) {
|
|
844
|
+
ev.preventDefault();
|
|
845
|
+
self.hideRows(boundRowIndexes[0], boundRowIndexes[1]);
|
|
846
|
+
},
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
//#endregion hide rows
|
|
852
|
+
|
|
853
|
+
//#region group/ungroup columns
|
|
854
|
+
const groupAreaHeight = self.getColumnGroupAreaHeight();
|
|
855
|
+
const groupAreaWidth = self.getRowGroupAreaWidth();
|
|
856
|
+
const setCollapseStateForAllGroups = (allGroups, collapsed) => {
|
|
857
|
+
if (allGroups.length === 0) return;
|
|
858
|
+
for (let i = 0; i < allGroups.length; i++) {
|
|
859
|
+
const groups = allGroups[i];
|
|
860
|
+
for (let j = 0; j < groups.length; j++) {
|
|
861
|
+
const group = groups[j];
|
|
862
|
+
group.collapsed = collapsed;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
self.refresh();
|
|
866
|
+
};
|
|
867
|
+
if (e.pos && e.pos.y < groupAreaHeight) {
|
|
868
|
+
e.items.push({
|
|
869
|
+
title: self.attributes.showRemoveAllGroupColumns,
|
|
870
|
+
click: function (ev) {
|
|
871
|
+
ev.preventDefault();
|
|
872
|
+
self.groupedColumns = [];
|
|
873
|
+
self.refresh();
|
|
874
|
+
},
|
|
875
|
+
});
|
|
876
|
+
e.items.push({
|
|
877
|
+
title: self.attributes.showExpandAllGroupColumns,
|
|
878
|
+
click: function (ev) {
|
|
879
|
+
ev.preventDefault();
|
|
880
|
+
setCollapseStateForAllGroups(self.groupedColumns, false);
|
|
881
|
+
},
|
|
882
|
+
});
|
|
883
|
+
e.items.push({
|
|
884
|
+
title: self.attributes.showCollapseAllGroupColumns,
|
|
885
|
+
click: function (ev) {
|
|
886
|
+
ev.preventDefault();
|
|
887
|
+
setCollapseStateForAllGroups(self.groupedColumns, true);
|
|
888
|
+
},
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
if (e.pos && e.pos.x < groupAreaWidth) {
|
|
892
|
+
e.items.push({
|
|
893
|
+
title: self.attributes.showRemoveAllGroupRows,
|
|
894
|
+
click: function (ev) {
|
|
895
|
+
ev.preventDefault();
|
|
896
|
+
self.groupedRows = [];
|
|
897
|
+
self.refresh();
|
|
898
|
+
},
|
|
899
|
+
});
|
|
900
|
+
e.items.push({
|
|
901
|
+
title: self.attributes.showExpandAllGroupRows,
|
|
902
|
+
click: function (ev) {
|
|
903
|
+
ev.preventDefault();
|
|
904
|
+
setCollapseStateForAllGroups(self.groupedRows, false);
|
|
905
|
+
},
|
|
906
|
+
});
|
|
907
|
+
e.items.push({
|
|
908
|
+
title: self.attributes.showCollapseAllGroupRows,
|
|
909
|
+
click: function (ev) {
|
|
910
|
+
ev.preventDefault();
|
|
911
|
+
setCollapseStateForAllGroups(self.groupedRows, true);
|
|
912
|
+
},
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
const canGroupByColumns =
|
|
917
|
+
self.attributes.allowGroupingColumns &&
|
|
918
|
+
e.cell.isColumnHeader &&
|
|
919
|
+
e.cell.header &&
|
|
920
|
+
e.cell.header.index > 0;
|
|
921
|
+
const canUngroupColumns =
|
|
922
|
+
self.attributes.allowGroupingColumns && e.cell.isColumnHeader;
|
|
923
|
+
const canGroupByRows =
|
|
924
|
+
!isSorting &&
|
|
925
|
+
self.attributes.allowGroupingRows &&
|
|
926
|
+
e.cell.isRowHeader &&
|
|
927
|
+
e.cell.header;
|
|
928
|
+
const canUngroupRows =
|
|
929
|
+
self.attributes.allowGroupingRows && e.cell.isRowHeader;
|
|
930
|
+
|
|
931
|
+
if (canGroupByColumns) {
|
|
932
|
+
/** @type {number[]} */
|
|
933
|
+
const groupIndexes = [];
|
|
934
|
+
/** @type {number} */
|
|
935
|
+
const headerIndex = e.cell.header.index;
|
|
936
|
+
let col = headerIndex;
|
|
937
|
+
for (; col >= 0; col--) {
|
|
938
|
+
if (!self.isColumnSelected(col)) break;
|
|
939
|
+
groupIndexes[0] = col;
|
|
940
|
+
}
|
|
941
|
+
for (col = headerIndex; ; col++) {
|
|
942
|
+
if (!self.isColumnSelected(col)) break;
|
|
943
|
+
groupIndexes[1] = col;
|
|
944
|
+
}
|
|
945
|
+
if (
|
|
946
|
+
col !== headerIndex &&
|
|
947
|
+
groupIndexes.length === 2 &&
|
|
948
|
+
groupIndexes[1] > groupIndexes[0] &&
|
|
949
|
+
self.isNewGroupRangeValid(
|
|
950
|
+
self.groupedColumns,
|
|
951
|
+
groupIndexes[0],
|
|
952
|
+
groupIndexes[1],
|
|
953
|
+
)
|
|
954
|
+
) {
|
|
955
|
+
const columns = getColumnsMap();
|
|
956
|
+
const groupTitles = [];
|
|
957
|
+
const groupNames = [];
|
|
958
|
+
for (let i = 0; i < groupIndexes.length; i++) {
|
|
959
|
+
const columnIndex = groupIndexes[i];
|
|
960
|
+
const column = columns.get(columnIndex);
|
|
961
|
+
if (column) {
|
|
962
|
+
groupNames.push(column.name);
|
|
963
|
+
groupTitles.push(column.title || column.name || column.index);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
if (groupNames[0] && groupNames[1]) {
|
|
967
|
+
// show group options
|
|
968
|
+
e.items.push({
|
|
969
|
+
title: self.attributes.showGroupColumns.replace(
|
|
970
|
+
'%s',
|
|
971
|
+
groupTitles[0] + '-' + groupTitles[1],
|
|
972
|
+
),
|
|
973
|
+
click: function (ev) {
|
|
974
|
+
ev.preventDefault();
|
|
975
|
+
self.groupColumns(groupNames[0], groupNames[1]);
|
|
976
|
+
self.controlInput.focus();
|
|
977
|
+
},
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
if (canUngroupColumns) {
|
|
983
|
+
const columnIndex = e.cell.columnIndex;
|
|
984
|
+
const groups = self.getGroupsColumnBelongsTo(columnIndex);
|
|
985
|
+
const columns = getColumnsMap();
|
|
986
|
+
for (let i = 0; i < groups.length; i++) {
|
|
987
|
+
const { from, to } = groups[i];
|
|
988
|
+
const cell0 = columns.get(from);
|
|
989
|
+
const cell1 = columns.get(to);
|
|
990
|
+
if (cell0 && cell1) {
|
|
991
|
+
const formatArgs =
|
|
992
|
+
(cell0.title || cell0.name || cell0.index) +
|
|
993
|
+
'-' +
|
|
994
|
+
(cell1.title || cell1.name || cell1.index);
|
|
995
|
+
e.items.push({
|
|
996
|
+
title: self.attributes.showRemoveGroupColumns.replace(
|
|
997
|
+
'%s',
|
|
998
|
+
formatArgs,
|
|
999
|
+
),
|
|
1000
|
+
click: function (ev) {
|
|
1001
|
+
ev.preventDefault();
|
|
1002
|
+
self.removeGroupColumns(cell0.name, cell1.name);
|
|
1003
|
+
self.controlInput.focus();
|
|
1004
|
+
},
|
|
1005
|
+
});
|
|
1006
|
+
} else {
|
|
1007
|
+
console.warn(`Cannot find column ${from} or column ${to}`);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
if (canGroupByRows) {
|
|
1012
|
+
const range = getSelectedContiguousRows(false) || [];
|
|
1013
|
+
const rangeTitle = range
|
|
1014
|
+
.map((rowIndex) => {
|
|
1015
|
+
const index = self.getBoundRowIndexFromViewRowIndex(rowIndex);
|
|
1016
|
+
if (typeof index === 'number') return index + 1;
|
|
1017
|
+
return rowIndex + 1;
|
|
1018
|
+
})
|
|
1019
|
+
.join('-');
|
|
1020
|
+
if (
|
|
1021
|
+
range.length === 2 &&
|
|
1022
|
+
self.isNewGroupRangeValid(self.groupedRows, range[0], range[1])
|
|
1023
|
+
) {
|
|
1024
|
+
e.items.push({
|
|
1025
|
+
title: self.attributes.showGroupRows.replace('%s', rangeTitle),
|
|
1026
|
+
click: function (ev) {
|
|
1027
|
+
ev.preventDefault();
|
|
1028
|
+
self.groupRows(range[0], range[1]);
|
|
1029
|
+
},
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
if (canUngroupRows) {
|
|
1034
|
+
const rowIndex = e.cell.rowIndex;
|
|
1035
|
+
const groups = self.getGroupsRowBelongsTo(rowIndex);
|
|
1036
|
+
for (let i = 0; i < groups.length; i++) {
|
|
1037
|
+
const { from, to } = groups[i];
|
|
1038
|
+
const rangeTitle = [from, to]
|
|
1039
|
+
.map((rowIndex) => {
|
|
1040
|
+
const index = self.getBoundRowIndexFromViewRowIndex(rowIndex);
|
|
1041
|
+
if (typeof index === 'number') return index + 1;
|
|
1042
|
+
return rowIndex + 1;
|
|
1043
|
+
})
|
|
1044
|
+
.join('-');
|
|
1045
|
+
e.items.push({
|
|
1046
|
+
title: self.attributes.showRemoveGroupRows.replace('%s', rangeTitle),
|
|
1047
|
+
click: function (ev) {
|
|
1048
|
+
ev.preventDefault();
|
|
1049
|
+
self.removeGroupRows(from, to);
|
|
1050
|
+
self.controlInput.focus();
|
|
1051
|
+
},
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
//#endregion group/ungroup columns
|
|
687
1056
|
}
|
|
688
1057
|
self.disposeAutocomplete = function () {
|
|
689
1058
|
if (autoCompleteContext) {
|
|
@@ -709,6 +1078,53 @@ export default function (self) {
|
|
|
709
1078
|
if (!self.hasFocus && e.target !== self.canvas) {
|
|
710
1079
|
return;
|
|
711
1080
|
}
|
|
1081
|
+
// don't create context menu for parents if current position is located in child grid
|
|
1082
|
+
const children = Object.keys(self.childGrids);
|
|
1083
|
+
for (let i = 0; i < children.length; i++) {
|
|
1084
|
+
const childGrid = self.childGrids[children[i]];
|
|
1085
|
+
const parentNode = childGrid && childGrid.parentNode;
|
|
1086
|
+
if (!parentNode) continue;
|
|
1087
|
+
const { offsetLeft, offsetWidth, offsetTop, offsetHeight } = parentNode;
|
|
1088
|
+
if ((e.x >= offsetLeft && e.x <= offsetLeft + offsetWidth) === false)
|
|
1089
|
+
continue;
|
|
1090
|
+
if ((e.y >= offsetTop && e.y <= offsetTop + offsetHeight) === false)
|
|
1091
|
+
continue;
|
|
1092
|
+
return; // in child grid
|
|
1093
|
+
}
|
|
1094
|
+
// don't create context menu for child if current position is located in parent grid
|
|
1095
|
+
if (self.isChildGrid && self.parentNode) {
|
|
1096
|
+
//#region check is current child grid closed
|
|
1097
|
+
const childGridsOfParent = self.parentGrid && self.parentGrid.childGrids;
|
|
1098
|
+
if (!childGridsOfParent || !Array.isArray(childGridsOfParent)) return;
|
|
1099
|
+
const matchedMe = childGridsOfParent.find((grid) => {
|
|
1100
|
+
const nodeA = grid.parentNode;
|
|
1101
|
+
const nodeB = self.parentNode;
|
|
1102
|
+
return (
|
|
1103
|
+
nodeA.offsetTop == nodeB.offsetTop &&
|
|
1104
|
+
nodeA.offsetLeft === nodeB.offsetLeft
|
|
1105
|
+
);
|
|
1106
|
+
});
|
|
1107
|
+
if (!matchedMe) return;
|
|
1108
|
+
//#endregion
|
|
1109
|
+
|
|
1110
|
+
let x0 = self.parentNode.offsetLeft;
|
|
1111
|
+
let x1 = self.parentNode.offsetLeft + self.parentNode.offsetWidth;
|
|
1112
|
+
let y0 = self.parentNode.offsetTop;
|
|
1113
|
+
let y1 = self.parentNode.offsetTop + self.parentNode.offsetHeight;
|
|
1114
|
+
let node = self.parentNode.parentNode;
|
|
1115
|
+
while (node) {
|
|
1116
|
+
const { offsetLeft, offsetWidth, offsetTop, offsetHeight } = node;
|
|
1117
|
+
if (offsetLeft > x0) x0 = offsetLeft;
|
|
1118
|
+
if (offsetTop > y0) y0 = offsetTop;
|
|
1119
|
+
const newX1 = offsetLeft + offsetWidth;
|
|
1120
|
+
const newY1 = offsetTop + offsetHeight;
|
|
1121
|
+
if (newX1 < x1) x1 = newX1;
|
|
1122
|
+
if (newY1 < y1) y1 = newY1;
|
|
1123
|
+
if (node.nodeType !== 'canvas-datagrid-tree') break;
|
|
1124
|
+
node = node.parentNode;
|
|
1125
|
+
}
|
|
1126
|
+
if ((e.x >= x0 && e.x <= x1 && e.y >= y0 && e.y <= y1) === false) return;
|
|
1127
|
+
}
|
|
712
1128
|
function createDisposeEvent() {
|
|
713
1129
|
requestAnimationFrame(function () {
|
|
714
1130
|
document.addEventListener('click', self.disposeContextMenu);
|
|
@@ -721,6 +1137,7 @@ export default function (self) {
|
|
|
721
1137
|
ev = {
|
|
722
1138
|
NativeEvent: e,
|
|
723
1139
|
cell: self.getCellAt(pos.x, pos.y),
|
|
1140
|
+
pos,
|
|
724
1141
|
items: items,
|
|
725
1142
|
};
|
|
726
1143
|
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],
|
|
@@ -43,6 +45,10 @@ export default function (self) {
|
|
|
43
45
|
['filterFrozenRows', true],
|
|
44
46
|
['globalRowResize', false],
|
|
45
47
|
['hideColumnText', 'Hide %s'],
|
|
48
|
+
['showUnhideColumnsIndicator', false],
|
|
49
|
+
['showUnhideRowsIndicator', false],
|
|
50
|
+
['showHideRow', 'Hide row %s'],
|
|
51
|
+
['showHideRows', 'Hide rows %s'],
|
|
46
52
|
['hoverMode', 'cell'],
|
|
47
53
|
['keepFocusOnMouseOut', false],
|
|
48
54
|
['maxAutoCompleteItems', 200],
|
|
@@ -55,6 +61,7 @@ export default function (self) {
|
|
|
55
61
|
['reorderDeadZone', 3],
|
|
56
62
|
['resizeScrollZone', 20],
|
|
57
63
|
['rowGrabZoneSize', 5],
|
|
64
|
+
['columnGrabZoneSize', 30],
|
|
58
65
|
['saveAppearance', true],
|
|
59
66
|
['scrollAnimationPPSThreshold', 0.75],
|
|
60
67
|
['scrollPointerLock', false],
|
|
@@ -74,6 +81,20 @@ export default function (self) {
|
|
|
74
81
|
['showOrderByOption', true],
|
|
75
82
|
['showOrderByOptionTextAsc', 'Order by %s ascending'],
|
|
76
83
|
['showOrderByOptionTextDesc', 'Order by %s descending'],
|
|
84
|
+
//#region grouping
|
|
85
|
+
['showGroupColumns', 'Group columns %s'],
|
|
86
|
+
['showGroupRows', 'Group rows %s'],
|
|
87
|
+
['showRemoveGroupColumns', 'Remove group %s'],
|
|
88
|
+
['showRemoveGroupRows', 'Remove group %s'],
|
|
89
|
+
['showRemoveAllGroupColumns', 'Remove all column groups'],
|
|
90
|
+
['showRemoveAllGroupRows', 'Remove all row groups'],
|
|
91
|
+
['showExpandAllGroupColumns', 'Expand all column groups'],
|
|
92
|
+
['showExpandAllGroupRows', 'Expand all row groups'],
|
|
93
|
+
['showCollapseAllGroupColumns', 'Collapse all column groups'],
|
|
94
|
+
['showCollapseAllGroupRows', 'Collapse all row groups'],
|
|
95
|
+
['columnGroupIndicatorPosition', 'right'],
|
|
96
|
+
['rowGroupIndicatorPosition', 'bottom'],
|
|
97
|
+
//#endregion grouping
|
|
77
98
|
['showPaste', false],
|
|
78
99
|
['showPerformance', false],
|
|
79
100
|
['showRowHeaders', true],
|
|
@@ -95,6 +116,11 @@ export default function (self) {
|
|
|
95
116
|
['maxPixelRatio', 2],
|
|
96
117
|
['tree', false],
|
|
97
118
|
['treeHorizontalScroll', false],
|
|
119
|
+
['rowTree', []],
|
|
120
|
+
['rowTreeColIndex', 0],
|
|
121
|
+
['columnTree', []],
|
|
122
|
+
['columnTreeRowStartIndex', 0],
|
|
123
|
+
['columnTreeRowEndIndex', 0],
|
|
98
124
|
],
|
|
99
125
|
styles: [
|
|
100
126
|
['activeCellBackgroundColor', 'rgba(255, 255, 255, 1)'],
|
|
@@ -149,6 +175,15 @@ export default function (self) {
|
|
|
149
175
|
['cellPaddingTop', 5],
|
|
150
176
|
['cellSelectedBackgroundColor', 'rgba(236, 243, 255, 1)'],
|
|
151
177
|
['cellSelectedColor', 'rgba(0, 0, 0, 1)'],
|
|
178
|
+
['cellTreeIconBorderColor', 'rgba(162, 174, 207, 1)'],
|
|
179
|
+
['cellTreeIconFillColor', 'rgba(240, 240, 240, 1)'],
|
|
180
|
+
['cellTreeIconHoverFillColor', 'rgba(198, 217, 233, 1)'],
|
|
181
|
+
['cellTreeIconLineColor', 'rgba(43, 53, 81, 1)'],
|
|
182
|
+
['cellTreeIconLineWidth', 1.5],
|
|
183
|
+
['cellTreeIconMarginLeft', 0],
|
|
184
|
+
['cellTreeIconMarginRight', 5],
|
|
185
|
+
['cellTreeIconMarginTop', 6],
|
|
186
|
+
['cellTreeIconWidth', 13],
|
|
152
187
|
['cellVerticalAlignment', 'center'],
|
|
153
188
|
['cellWidth', 250],
|
|
154
189
|
['cellWidthWithChildGrid', 250],
|
|
@@ -159,6 +194,7 @@ export default function (self) {
|
|
|
159
194
|
['childContextMenuArrowHTML', '►'],
|
|
160
195
|
['childContextMenuMarginLeft', -11],
|
|
161
196
|
['childContextMenuMarginTop', -6],
|
|
197
|
+
['columnGroupRowHeight', 25],
|
|
162
198
|
['columnHeaderCellBackgroundColor', 'rgba(240, 240, 240, 1)'],
|
|
163
199
|
['columnHeaderCellBorderColor', 'rgba(172, 172, 172, 1)'],
|
|
164
200
|
['columnHeaderCellBorderWidth', 1],
|
|
@@ -267,10 +303,13 @@ export default function (self) {
|
|
|
267
303
|
['frozenMarkerBorderColor', 'rgba(168, 168, 168, 1)'],
|
|
268
304
|
['frozenMarkerBorderWidth', 1],
|
|
269
305
|
['frozenMarkerWidth', 2],
|
|
306
|
+
['groupingAreaBackgroundColor', 'rgba(240, 240, 240, 1)'],
|
|
270
307
|
['gridBackgroundColor', 'rgba(240, 240, 240, 1)'],
|
|
271
308
|
['gridBorderCollapse', 'collapse'],
|
|
272
309
|
['gridBorderColor', 'rgba(202, 202, 202, 1)'],
|
|
273
310
|
['gridBorderWidth', 1],
|
|
311
|
+
['groupIndicatorColor', 'rgba(155, 155, 155, 1)'],
|
|
312
|
+
['groupIndicatorBackgroundColor', 'rgba(255, 255, 255, 1)'],
|
|
274
313
|
['height', 'auto'],
|
|
275
314
|
['maxHeight', 'inherit'],
|
|
276
315
|
['maxWidth', 'inherit'],
|
|
@@ -293,6 +332,7 @@ export default function (self) {
|
|
|
293
332
|
['reorderMarkerBorderWidth', 1.25],
|
|
294
333
|
['reorderMarkerIndexBorderColor', 'rgba(66, 133, 244, 1)'],
|
|
295
334
|
['reorderMarkerIndexBorderWidth', 2.75],
|
|
335
|
+
['rowGroupColumnWidth', 25],
|
|
296
336
|
['rowHeaderCellBackgroundColor', 'rgba(240, 240, 240, 1)'],
|
|
297
337
|
['rowHeaderCellBorderColor', 'rgba(200, 200, 200, 1)'],
|
|
298
338
|
['rowHeaderCellBorderWidth', 1],
|
|
@@ -341,6 +381,10 @@ export default function (self) {
|
|
|
341
381
|
['treeArrowMarginTop', 6],
|
|
342
382
|
['treeArrowWidth', 13],
|
|
343
383
|
['treeGridHeight', 250],
|
|
384
|
+
['unhideIndicatorColor', 'rgba(0, 0, 0, 1)'],
|
|
385
|
+
['unhideIndicatorBackgroundColor', 'rgba(255, 255, 255, 1)'],
|
|
386
|
+
['unhideIndicatorBorderColor', 'rgba(174, 193, 232, 1)'],
|
|
387
|
+
['unhideIndicatorSize', 16],
|
|
344
388
|
['width', 'auto'],
|
|
345
389
|
],
|
|
346
390
|
};
|
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=►] - 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.
|
package/lib/dom.js
CHANGED
|
@@ -123,14 +123,27 @@ export default function (self) {
|
|
|
123
123
|
self.input.style.width = self.width - borderWidth - 1 + 'px';
|
|
124
124
|
return;
|
|
125
125
|
}
|
|
126
|
+
let groupAreaOffsetY = self.getColumnGroupAreaHeight();
|
|
127
|
+
let groupAreaOffsetX = self.getRowGroupAreaWidth();
|
|
128
|
+
if (self.parentNode) {
|
|
129
|
+
const { columnGroupsAreaHeight, rowGroupsAreaWidth } = self.parentNode;
|
|
130
|
+
if (columnGroupsAreaHeight) groupAreaOffsetY += columnGroupsAreaHeight;
|
|
131
|
+
if (rowGroupsAreaWidth) groupAreaOffsetX += rowGroupsAreaWidth;
|
|
132
|
+
}
|
|
126
133
|
self.input.style.left =
|
|
127
|
-
pos.left +
|
|
134
|
+
pos.left +
|
|
135
|
+
cell.x +
|
|
136
|
+
self.canvasOffsetLeft -
|
|
137
|
+
s.left +
|
|
138
|
+
groupAreaOffsetX +
|
|
139
|
+
'px';
|
|
128
140
|
self.input.style.top =
|
|
129
141
|
pos.top +
|
|
130
142
|
cell.y -
|
|
131
143
|
self.style.cellBorderWidth +
|
|
132
144
|
self.canvasOffsetTop -
|
|
133
145
|
s.top +
|
|
146
|
+
groupAreaOffsetY +
|
|
134
147
|
'px';
|
|
135
148
|
self.input.style.height = cell.height - borderWidth + 'px';
|
|
136
149
|
self.input.style.width = cell.width - self.style.cellPaddingLeft + 'px';
|
|
@@ -171,6 +184,10 @@ export default function (self) {
|
|
|
171
184
|
if (self.isChildGrid) {
|
|
172
185
|
pos.x -= self.canvasOffsetLeft;
|
|
173
186
|
pos.y -= self.canvasOffsetTop;
|
|
187
|
+
if (self.parentNode.rowGroupsAreaWidth)
|
|
188
|
+
pos.x -= self.parentNode.rowGroupsAreaWidth;
|
|
189
|
+
if (self.parentNode.columnGroupsAreaHeight)
|
|
190
|
+
pos.y -= self.parentNode.columnGroupsAreaHeight;
|
|
174
191
|
}
|
|
175
192
|
return {
|
|
176
193
|
x: pos.x,
|