canvas-datagrid 0.3.25 → 0.4.0
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 +13 -0
- package/dist/canvas-datagrid.debug.js +2211 -109
- 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 +114 -0
- package/lib/contextMenu.js +283 -0
- package/lib/defaults.js +35 -0
- package/lib/docs.js +18 -0
- package/lib/dom.js +18 -1
- package/lib/draw.js +626 -30
- package/lib/events/index.js +122 -23
- package/lib/events/util.js +1 -1
- package/lib/intf.js +572 -0
- package/lib/publicMethods.js +359 -0
- package/package.json +1 -1
package/lib/publicMethods.js
CHANGED
|
@@ -331,6 +331,39 @@ export default function (self) {
|
|
|
331
331
|
imgSrc,
|
|
332
332
|
);
|
|
333
333
|
};
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Expand/Collapse CellTree.
|
|
337
|
+
* @memberof canvasDatagrid
|
|
338
|
+
* @name toggleCellCollapseTree
|
|
339
|
+
* @method
|
|
340
|
+
* @param {array} treeData The array of cellTree to expand or collapse.
|
|
341
|
+
*/
|
|
342
|
+
|
|
343
|
+
self.toggleCellCollapseTree = function (treeData) {
|
|
344
|
+
for (let type in treeData) {
|
|
345
|
+
for (let t of treeData[type])
|
|
346
|
+
if (t.length > 0) self.toggleCollapseTree(t[0], t[1], type);
|
|
347
|
+
}
|
|
348
|
+
self.draw();
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Expand/Collapse CellTree.
|
|
353
|
+
* @memberof canvasDatagrid
|
|
354
|
+
* @name expandCollapseCellTree
|
|
355
|
+
* @method
|
|
356
|
+
* @param {array} treeData The array of cellTree to expand or collapse.
|
|
357
|
+
*/
|
|
358
|
+
|
|
359
|
+
self.expandCollapseCellTree = function (treeData) {
|
|
360
|
+
for (let type in treeData) {
|
|
361
|
+
for (let t of treeData[type])
|
|
362
|
+
if (t.length > 0) self.cellTreeExpandCollapse(t[0], t[1], type);
|
|
363
|
+
}
|
|
364
|
+
self.draw();
|
|
365
|
+
};
|
|
366
|
+
|
|
334
367
|
/**
|
|
335
368
|
* Scrolls the cell at cell x, row y into view if it is not already.
|
|
336
369
|
* @memberof canvasDatagrid
|
|
@@ -853,6 +886,244 @@ export default function (self) {
|
|
|
853
886
|
}
|
|
854
887
|
self.setStorageData();
|
|
855
888
|
};
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Add grouping
|
|
892
|
+
* @param {'columns'|'rows'} groupFor
|
|
893
|
+
* @param {number} from
|
|
894
|
+
* @param {number} to
|
|
895
|
+
*/
|
|
896
|
+
function addGroup(groupFor, from, to) {
|
|
897
|
+
let newRow = false;
|
|
898
|
+
const allGroups =
|
|
899
|
+
groupFor === 'rows' ? self.groupedRows : self.groupedColumns;
|
|
900
|
+
for (let i = allGroups.length - 1; i >= 0; i--) {
|
|
901
|
+
const groups = allGroups[i];
|
|
902
|
+
const min = groups[0].from,
|
|
903
|
+
max = groups[groups.length - 1].to;
|
|
904
|
+
if (from <= min && to >= max) {
|
|
905
|
+
if (from === min && to === max && groups.length === 1) return; // nothings happened
|
|
906
|
+
// new group wrap this row
|
|
907
|
+
continue;
|
|
908
|
+
}
|
|
909
|
+
for (let gi = 0; gi < groups.length; gi++) {
|
|
910
|
+
const g = groups[gi];
|
|
911
|
+
if (from > g.to) continue;
|
|
912
|
+
if (from >= g.from) {
|
|
913
|
+
if (to > g.to) {
|
|
914
|
+
if (from === g.from) {
|
|
915
|
+
allGroups.splice(i, 0, [{ from, to, collapsed: false }]);
|
|
916
|
+
self.refresh();
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
throw new Error(`Can't group these ${groupFor}`);
|
|
920
|
+
}
|
|
921
|
+
if (to === g.to) {
|
|
922
|
+
if (from === g.from) return; // nothings happened
|
|
923
|
+
}
|
|
924
|
+
newRow = true;
|
|
925
|
+
break;
|
|
926
|
+
}
|
|
927
|
+
if (to >= g.from) {
|
|
928
|
+
if (to < g.to) throw new Error(`Can't group these ${groupFor}`);
|
|
929
|
+
allGroups.splice(i, 0, [{ from, to, collapsed: false }]);
|
|
930
|
+
} else {
|
|
931
|
+
groups.splice(gi, 0, { from, to, collapsed: false });
|
|
932
|
+
}
|
|
933
|
+
self.refresh();
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
if (newRow) continue;
|
|
937
|
+
groups.push({ from, to, collapsed: false });
|
|
938
|
+
self.refresh();
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
if (newRow) allGroups.push([{ from, to, collapsed: false }]);
|
|
942
|
+
else allGroups.unshift([{ from, to, collapsed: false }]);
|
|
943
|
+
self.refresh();
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* Remove grouping
|
|
947
|
+
* @param {Array<Array<{from:number,to:number,collapsed:boolean}>>} allGroups
|
|
948
|
+
* @param {number} from
|
|
949
|
+
* @param {number} to
|
|
950
|
+
*/
|
|
951
|
+
function removeGroup(allGroups, from, to) {
|
|
952
|
+
for (let i = 0; i < allGroups.length; i++) {
|
|
953
|
+
const groups = allGroups[i];
|
|
954
|
+
for (let gi = 0; gi < groups.length; gi++) {
|
|
955
|
+
const group = groups[gi];
|
|
956
|
+
if (group.from === from && group.to === to) {
|
|
957
|
+
if (groups.length <= 1) allGroups.splice(i, 1);
|
|
958
|
+
else groups.splice(gi, 1);
|
|
959
|
+
self.refresh();
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Grouping columns
|
|
967
|
+
* @memberof canvasDatagrid
|
|
968
|
+
* @name groupColumns
|
|
969
|
+
* @method
|
|
970
|
+
* @param {number|string} firstColumnName Name of the first column to be grouped.
|
|
971
|
+
* @param {number|string} lastColumnName Name of the last column to be grouped.
|
|
972
|
+
*/
|
|
973
|
+
self.groupColumns = function (firstColumnName, lastColumnName) {
|
|
974
|
+
/** @type {Array<{name: string,columnIndex:number}>} */
|
|
975
|
+
const schema = self.getSchema();
|
|
976
|
+
let firstOne, lastOne;
|
|
977
|
+
for (let i = 0; i < schema.length; i++) {
|
|
978
|
+
const it = schema[i];
|
|
979
|
+
if (firstOne && lastOne) break;
|
|
980
|
+
if (it.name === firstColumnName) {
|
|
981
|
+
firstOne = it;
|
|
982
|
+
continue;
|
|
983
|
+
}
|
|
984
|
+
if (it.name === lastColumnName) {
|
|
985
|
+
lastOne = it;
|
|
986
|
+
continue;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
if (!firstOne) throw new Error(`No such column name for first column`);
|
|
990
|
+
if (!lastOne) throw new Error(`No such column name for last column`);
|
|
991
|
+
if (lastOne.columnIndex > firstOne.columnIndex !== true)
|
|
992
|
+
throw new Error(`Can't group these columns`);
|
|
993
|
+
|
|
994
|
+
const from = firstOne.columnIndex;
|
|
995
|
+
const to = lastOne.columnIndex;
|
|
996
|
+
const ev = { group: { type: 'columns', from, to } };
|
|
997
|
+
try {
|
|
998
|
+
addGroup('columns', from, to);
|
|
999
|
+
} catch (error) {
|
|
1000
|
+
ev.error = error;
|
|
1001
|
+
}
|
|
1002
|
+
self.dispatchEvent('aftercreategroup', ev);
|
|
1003
|
+
};
|
|
1004
|
+
/**
|
|
1005
|
+
* Grouping columns
|
|
1006
|
+
* @memberof canvasDatagrid
|
|
1007
|
+
* @name groupRows
|
|
1008
|
+
* @method
|
|
1009
|
+
* @param {number} rowIndexFrom The row index which is the beginning of the group
|
|
1010
|
+
* @param {number} rowIndexTo The row index which is the end of the group
|
|
1011
|
+
*/
|
|
1012
|
+
self.groupRows = function (rowIndexFrom, rowIndexTo) {
|
|
1013
|
+
if (!Number.isInteger(rowIndexFrom) || rowIndexFrom < 0)
|
|
1014
|
+
throw new Error(`No such row for the beginning of the group`);
|
|
1015
|
+
|
|
1016
|
+
const dataLength = self.viewData.length;
|
|
1017
|
+
if (
|
|
1018
|
+
!Number.isInteger(rowIndexFrom) ||
|
|
1019
|
+
rowIndexTo <= rowIndexFrom ||
|
|
1020
|
+
rowIndexTo >= dataLength
|
|
1021
|
+
)
|
|
1022
|
+
throw new Error(`No such row for the end of the group`);
|
|
1023
|
+
const ev = {
|
|
1024
|
+
group: {
|
|
1025
|
+
type: 'rows',
|
|
1026
|
+
from: rowIndexFrom,
|
|
1027
|
+
to: rowIndexTo,
|
|
1028
|
+
},
|
|
1029
|
+
};
|
|
1030
|
+
try {
|
|
1031
|
+
addGroup('rows', rowIndexFrom, rowIndexTo);
|
|
1032
|
+
} catch (error) {
|
|
1033
|
+
ev.error = error;
|
|
1034
|
+
}
|
|
1035
|
+
self.dispatchEvent('aftercreategroup', ev);
|
|
1036
|
+
};
|
|
1037
|
+
/**
|
|
1038
|
+
* Remove grouping columns
|
|
1039
|
+
* @memberof canvasDatagrid
|
|
1040
|
+
* @name removeGroupColumns
|
|
1041
|
+
* @method
|
|
1042
|
+
* @param {number|string} firstColumnName Name of the first column to be grouped.
|
|
1043
|
+
* @param {number|string} lastColumnName Name of the last column to be grouped.
|
|
1044
|
+
*/
|
|
1045
|
+
self.removeGroupColumns = function (firstColumnName, lastColumnName) {
|
|
1046
|
+
/** @type {Array<{name:string,columnIndex:number}>} */
|
|
1047
|
+
const schema = self.getSchema();
|
|
1048
|
+
let firstOne, lastOne;
|
|
1049
|
+
for (let i = 0; i < schema.length; i++) {
|
|
1050
|
+
const it = schema[i];
|
|
1051
|
+
if (firstOne && lastOne) break;
|
|
1052
|
+
if (it.name === firstColumnName) {
|
|
1053
|
+
firstOne = it;
|
|
1054
|
+
continue;
|
|
1055
|
+
}
|
|
1056
|
+
if (it.name === lastColumnName) {
|
|
1057
|
+
lastOne = it;
|
|
1058
|
+
continue;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
if (!firstOne) throw new Error(`No such column name for first column`);
|
|
1062
|
+
if (!lastOne) throw new Error(`No such column name for last column`);
|
|
1063
|
+
const from = firstOne.columnIndex;
|
|
1064
|
+
const to = lastOne.columnIndex;
|
|
1065
|
+
removeGroup(self.groupedColumns, from, to);
|
|
1066
|
+
};
|
|
1067
|
+
/**
|
|
1068
|
+
* Remove grouping columns
|
|
1069
|
+
* @memberof canvasDatagrid
|
|
1070
|
+
* @name removeGroupRows
|
|
1071
|
+
* @method
|
|
1072
|
+
* @param {number} rowIndexFrom The row index which is the beginning of the group
|
|
1073
|
+
* @param {number} rowIndexTo The row index which is the end of the group
|
|
1074
|
+
*/
|
|
1075
|
+
self.removeGroupRows = function (rowIndexFrom, rowIndexTo) {
|
|
1076
|
+
removeGroup(self.groupedRows, rowIndexFrom, rowIndexTo);
|
|
1077
|
+
};
|
|
1078
|
+
/**
|
|
1079
|
+
* Toggle(expand/collapsed) grouping columns
|
|
1080
|
+
* @memberof canvasDatagrid
|
|
1081
|
+
* @name toggleGroupColumns
|
|
1082
|
+
* @method
|
|
1083
|
+
* @param {number|string} firstColumnName Name of the first column to be grouped.
|
|
1084
|
+
* @param {number|string} lastColumnName Name of the last column to be grouped.
|
|
1085
|
+
*/
|
|
1086
|
+
self.toggleGroupColumns = function (firstColumnName, lastColumnName) {
|
|
1087
|
+
/** @type {Array<{name:string,columnIndex:number}>} */
|
|
1088
|
+
const schema = self.getSchema();
|
|
1089
|
+
let firstOne, lastOne;
|
|
1090
|
+
for (let i = 0; i < schema.length; i++) {
|
|
1091
|
+
const it = schema[i];
|
|
1092
|
+
if (firstOne && lastOne) break;
|
|
1093
|
+
if (it.name === firstColumnName) {
|
|
1094
|
+
firstOne = it;
|
|
1095
|
+
continue;
|
|
1096
|
+
}
|
|
1097
|
+
if (it.name === lastColumnName) {
|
|
1098
|
+
lastOne = it;
|
|
1099
|
+
continue;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
if (!firstOne || !lastOne) return;
|
|
1103
|
+
const from = firstOne.columnIndex;
|
|
1104
|
+
const to = lastOne.columnIndex;
|
|
1105
|
+
if (self.toggleGroup({ type: 'c', from, to })) {
|
|
1106
|
+
self.disposeContextMenu();
|
|
1107
|
+
self.setStorageData();
|
|
1108
|
+
self.refresh();
|
|
1109
|
+
}
|
|
1110
|
+
};
|
|
1111
|
+
/**
|
|
1112
|
+
* Toggle(expand/collapsed) grouping rows
|
|
1113
|
+
* @memberof canvasDatagrid
|
|
1114
|
+
* @name toggleGroupRows
|
|
1115
|
+
* @method
|
|
1116
|
+
* @param {number} rowIndexFrom The row index which is the beginning of the group
|
|
1117
|
+
* @param {number} rowIndexTo The row index which is the end of the group
|
|
1118
|
+
*/
|
|
1119
|
+
self.toggleGroupRows = function (rowIndexFrom, rowIndexTo) {
|
|
1120
|
+
if (self.toggleGroup({ type: 'r', from: rowIndexFrom, to: rowIndexTo })) {
|
|
1121
|
+
self.disposeContextMenu();
|
|
1122
|
+
self.setStorageData();
|
|
1123
|
+
self.refresh();
|
|
1124
|
+
}
|
|
1125
|
+
};
|
|
1126
|
+
|
|
856
1127
|
self.isInGrid = function (e) {
|
|
857
1128
|
if (e.x < 0 || e.x > self.width || e.y < 0 || e.y > self.height) {
|
|
858
1129
|
return false;
|
|
@@ -931,6 +1202,9 @@ export default function (self) {
|
|
|
931
1202
|
return;
|
|
932
1203
|
}
|
|
933
1204
|
// TODO:
|
|
1205
|
+
if (!self.data) {
|
|
1206
|
+
self.data = {};
|
|
1207
|
+
}
|
|
934
1208
|
if (!self.data[rowIndex]) {
|
|
935
1209
|
self.data[rowIndex] = {};
|
|
936
1210
|
}
|
|
@@ -971,6 +1245,53 @@ export default function (self) {
|
|
|
971
1245
|
});
|
|
972
1246
|
});
|
|
973
1247
|
};
|
|
1248
|
+
/**
|
|
1249
|
+
* Get the column group info given column belongs to
|
|
1250
|
+
* @memberof canvasDatagrid
|
|
1251
|
+
* @name getGroupsColumnBelongsTo
|
|
1252
|
+
* @method
|
|
1253
|
+
* @param {number} columnIndex Column index.
|
|
1254
|
+
* @returns {Array<{from:number,to:number,collapsed:boolean}>}
|
|
1255
|
+
*/
|
|
1256
|
+
self.getGroupsColumnBelongsTo = function (columnIndex) {
|
|
1257
|
+
if (!self.attributes.allowGroupingColumns) return [];
|
|
1258
|
+
const result = [];
|
|
1259
|
+
for (let i = 0; i < self.groupedColumns.length; i++) {
|
|
1260
|
+
const groups = self.groupedColumns[i];
|
|
1261
|
+
for (let j = 0; j < groups.length; j++) {
|
|
1262
|
+
const group = groups[j];
|
|
1263
|
+
if (columnIndex >= group.from && columnIndex <= group.to) {
|
|
1264
|
+
result.push(group);
|
|
1265
|
+
break;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
return result;
|
|
1270
|
+
};
|
|
1271
|
+
/**
|
|
1272
|
+
* Get the row group info given row belongs to
|
|
1273
|
+
* @memberof canvasDatagrid
|
|
1274
|
+
* @name getGroupsRowBelongsTo
|
|
1275
|
+
* @method
|
|
1276
|
+
* @param {number} rowIndex Row index.
|
|
1277
|
+
* @returns {Array<{from:number,to:number,collapsed:boolean}>}
|
|
1278
|
+
*/
|
|
1279
|
+
self.getGroupsRowBelongsTo = function (rowIndex) {
|
|
1280
|
+
if (!self.attributes.allowGroupingRows) return [];
|
|
1281
|
+
const result = [];
|
|
1282
|
+
for (let i = 0; i < self.groupedRows.length; i++) {
|
|
1283
|
+
const groups = self.groupedRows[i];
|
|
1284
|
+
for (let j = 0; j < groups.length; j++) {
|
|
1285
|
+
const group = groups[j];
|
|
1286
|
+
if (rowIndex >= group.from && rowIndex <= group.to) {
|
|
1287
|
+
result.push(group);
|
|
1288
|
+
break;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
return result;
|
|
1293
|
+
};
|
|
1294
|
+
|
|
974
1295
|
/**
|
|
975
1296
|
* Checks if a given column is visible.
|
|
976
1297
|
* @memberof canvasDatagrid
|
|
@@ -1015,6 +1336,42 @@ export default function (self) {
|
|
|
1015
1336
|
return c.columnIndex === x && c.rowIndex === y;
|
|
1016
1337
|
})[0];
|
|
1017
1338
|
};
|
|
1339
|
+
/**
|
|
1340
|
+
* @memberof canvasDatagrid
|
|
1341
|
+
* @name getColumnGroupAt
|
|
1342
|
+
* @method
|
|
1343
|
+
* @param {number} x Number of pixels from the left.
|
|
1344
|
+
* @param {number} y Number of pixels from the top.
|
|
1345
|
+
*/
|
|
1346
|
+
self.getColumnGroupAt = function (x, y) {
|
|
1347
|
+
const groups = self.groupedColumns.length;
|
|
1348
|
+
if (groups <= 0) return;
|
|
1349
|
+
const yZero = self.getColumnGroupAreaHeight();
|
|
1350
|
+
if (y >= yZero) return;
|
|
1351
|
+
for (let i = 0; i < self.visibleGroups.length; i++) {
|
|
1352
|
+
const g = self.visibleGroups[i];
|
|
1353
|
+
if (g.type !== 'c') continue;
|
|
1354
|
+
if (x >= g.x && y >= g.y && x <= g.x2 && y <= g.y2) return g;
|
|
1355
|
+
}
|
|
1356
|
+
};
|
|
1357
|
+
/**
|
|
1358
|
+
* @memberof canvasDatagrid
|
|
1359
|
+
* @name getRowGroupAt
|
|
1360
|
+
* @method
|
|
1361
|
+
* @param {number} x Number of pixels from the left.
|
|
1362
|
+
* @param {number} y Number of pixels from the top.
|
|
1363
|
+
*/
|
|
1364
|
+
self.getRowGroupAt = function (x, y) {
|
|
1365
|
+
const groups = self.groupedRows.length;
|
|
1366
|
+
if (groups <= 0) return;
|
|
1367
|
+
const xZero = self.getRowGroupAreaWidth();
|
|
1368
|
+
if (x >= xZero) return;
|
|
1369
|
+
for (let i = 0; i < self.visibleGroups.length; i++) {
|
|
1370
|
+
const g = self.visibleGroups[i];
|
|
1371
|
+
if (g.type !== 'r') continue;
|
|
1372
|
+
if (x >= g.x && y >= g.y && x <= g.x2 && y <= g.y2) return g;
|
|
1373
|
+
}
|
|
1374
|
+
};
|
|
1018
1375
|
/**
|
|
1019
1376
|
* 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.
|
|
1020
1377
|
* @memberof canvasDatagrid
|
|
@@ -1056,6 +1413,8 @@ export default function (self) {
|
|
|
1056
1413
|
if (!self.visibleCells) {
|
|
1057
1414
|
return;
|
|
1058
1415
|
}
|
|
1416
|
+
x -= self.getRowGroupAreaWidth();
|
|
1417
|
+
y -= self.getColumnGroupAreaHeight();
|
|
1059
1418
|
var border,
|
|
1060
1419
|
tsz = useTouchScrollZones ? self.attributes.touchScrollZone : 0,
|
|
1061
1420
|
moveMode = self.attributes.borderDragBehavior === 'move',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "canvas-datagrid",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
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",
|