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.
@@ -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.25",
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",