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.
@@ -1217,10 +1217,14 @@ function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "functi
1217
1217
  });
1218
1218
 
1219
1219
  if (e.cell && e.cell.header && e.cell.columnIndex > -1) {
1220
+ // This variable represents the order index because of the following codes from `draw.js`:
1221
+ // columnIndex: columnOrderIndex,
1222
+ var columnOrderIndex = e.cell.columnIndex;
1223
+ var columnIndex = self.orders.columns[columnOrderIndex];
1220
1224
  e.items.push({
1221
1225
  title: self.attributes.hideColumnText.replace(/%s/gi, e.cell.header.title || e.cell.header.name),
1222
1226
  click: function click(ev) {
1223
- self.getSchema()[e.cell.columnIndex].hidden = true;
1227
+ self.getSchema()[columnIndex].hidden = true;
1224
1228
  ev.preventDefault();
1225
1229
  self.stopPropagation(ev);
1226
1230
  self.disposeContextMenu();
@@ -1275,7 +1279,256 @@ function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "functi
1275
1279
  self.controlInput.focus();
1276
1280
  }
1277
1281
  });
1282
+ } //#region group/ungroup columns
1283
+
1284
+
1285
+ var groupAreaHeight = self.getColumnGroupAreaHeight();
1286
+ var groupAreaWidth = self.getRowGroupAreaWidth();
1287
+
1288
+ var setCollapseStateForAllGroups = function setCollapseStateForAllGroups(allGroups, collapsed) {
1289
+ if (allGroups.length === 0) return;
1290
+
1291
+ for (var i = 0; i < allGroups.length; i++) {
1292
+ var groups = allGroups[i];
1293
+
1294
+ for (var j = 0; j < groups.length; j++) {
1295
+ var group = groups[j];
1296
+ group.collapsed = collapsed;
1297
+ }
1298
+ }
1299
+
1300
+ self.refresh();
1301
+ };
1302
+
1303
+ if (e.pos && e.pos.y < groupAreaHeight) {
1304
+ e.items.push({
1305
+ title: self.attributes.showRemoveAllGroupColumns,
1306
+ click: function click(ev) {
1307
+ ev.preventDefault();
1308
+ self.groupedColumns = [];
1309
+ self.refresh();
1310
+ }
1311
+ });
1312
+ e.items.push({
1313
+ title: self.attributes.showExpandAllGroupColumns,
1314
+ click: function click(ev) {
1315
+ ev.preventDefault();
1316
+ setCollapseStateForAllGroups(self.groupedColumns, false);
1317
+ }
1318
+ });
1319
+ e.items.push({
1320
+ title: self.attributes.showCollapseAllGroupColumns,
1321
+ click: function click(ev) {
1322
+ ev.preventDefault();
1323
+ setCollapseStateForAllGroups(self.groupedColumns, true);
1324
+ }
1325
+ });
1326
+ }
1327
+
1328
+ if (e.pos && e.pos.x < groupAreaWidth) {
1329
+ e.items.push({
1330
+ title: self.attributes.showRemoveAllGroupRows,
1331
+ click: function click(ev) {
1332
+ ev.preventDefault();
1333
+ self.groupedRows = [];
1334
+ self.refresh();
1335
+ }
1336
+ });
1337
+ e.items.push({
1338
+ title: self.attributes.showExpandAllGroupRows,
1339
+ click: function click(ev) {
1340
+ ev.preventDefault();
1341
+ setCollapseStateForAllGroups(self.groupedRows, false);
1342
+ }
1343
+ });
1344
+ e.items.push({
1345
+ title: self.attributes.showCollapseAllGroupRows,
1346
+ click: function click(ev) {
1347
+ ev.preventDefault();
1348
+ setCollapseStateForAllGroups(self.groupedRows, true);
1349
+ }
1350
+ });
1351
+ }
1352
+
1353
+ var canGroupByColumns = self.attributes.allowGroupingColumns && e.cell.isColumnHeader && e.cell.header && e.cell.header.index > 0;
1354
+ var canUngroupColumns = self.attributes.allowGroupingColumns && e.cell.isColumnHeader;
1355
+ var canGroupByRows = self.attributes.allowGroupingRows && e.cell.isRowHeader && e.cell.header;
1356
+ var canUngroupRows = self.attributes.allowGroupingRows && e.cell.isRowHeader;
1357
+ /**
1358
+ * The value for storing the return value from `self.getSchema()`
1359
+ * @type {any[]}
1360
+ */
1361
+
1362
+ var schema;
1363
+ /**
1364
+ * A map between columnIndex and column data
1365
+ * @type {Map<string,any>}
1366
+ */
1367
+
1368
+ var columns;
1369
+
1370
+ var getColumnsMap = function getColumnsMap() {
1371
+ if (!columns) {
1372
+ if (!schema) schema = self.getSchema();
1373
+ columns = new Map(schema.map(function (_col) {
1374
+ return [_col.columnIndex, _col];
1375
+ }));
1376
+ }
1377
+
1378
+ return columns;
1379
+ };
1380
+
1381
+ if (canGroupByColumns) {
1382
+ /** @type {number[]} */
1383
+ var groupIndexes = [];
1384
+ /** @type {number} */
1385
+
1386
+ var headerIndex = e.cell.header.index;
1387
+ var col = headerIndex;
1388
+
1389
+ for (; col >= 0; col--) {
1390
+ if (!self.isColumnSelected(col)) break;
1391
+ groupIndexes[0] = col;
1392
+ }
1393
+
1394
+ for (col = headerIndex;; col++) {
1395
+ if (!self.isColumnSelected(col)) break;
1396
+ groupIndexes[1] = col;
1397
+ }
1398
+
1399
+ if (col !== headerIndex && groupIndexes.length === 2 && groupIndexes[1] > groupIndexes[0] && self.isNewGroupRangeValid(self.groupedColumns, groupIndexes[0], groupIndexes[1])) {
1400
+ var _columns = getColumnsMap();
1401
+
1402
+ var groupTitles = [];
1403
+ var groupNames = [];
1404
+
1405
+ for (var i = 0; i < groupIndexes.length; i++) {
1406
+ var _columnIndex = groupIndexes[i];
1407
+
1408
+ var column = _columns.get(_columnIndex);
1409
+
1410
+ if (column) {
1411
+ groupNames.push(column.name);
1412
+ groupTitles.push(column.title || column.name || column.index);
1413
+ }
1414
+ }
1415
+
1416
+ if (groupNames[0] && groupNames[1]) {
1417
+ // show group options
1418
+ e.items.push({
1419
+ title: self.attributes.showGroupColumns.replace('%s', groupTitles[0] + '-' + groupTitles[1]),
1420
+ click: function click(ev) {
1421
+ ev.preventDefault();
1422
+ self.groupColumns(groupNames[0], groupNames[1]);
1423
+ self.controlInput.focus();
1424
+ }
1425
+ });
1426
+ }
1427
+ }
1428
+ }
1429
+
1430
+ if (canUngroupColumns) {
1431
+ var _columnIndex2 = e.cell.columnIndex;
1432
+ var groups = self.getGroupsColumnBelongsTo(_columnIndex2);
1433
+
1434
+ var _columns2 = getColumnsMap();
1435
+
1436
+ var _loop = function _loop(_i) {
1437
+ var _groups$_i = groups[_i],
1438
+ from = _groups$_i.from,
1439
+ to = _groups$_i.to;
1440
+
1441
+ var cell0 = _columns2.get(from);
1442
+
1443
+ var cell1 = _columns2.get(to);
1444
+
1445
+ if (cell0 && cell1) {
1446
+ var formatArgs = (cell0.title || cell0.name || cell0.index) + '-' + (cell1.title || cell1.name || cell1.index);
1447
+ e.items.push({
1448
+ title: self.attributes.showRemoveGroupColumns.replace('%s', formatArgs),
1449
+ click: function click(ev) {
1450
+ ev.preventDefault();
1451
+ self.removeGroupColumns(cell0.name, cell1.name);
1452
+ self.controlInput.focus();
1453
+ }
1454
+ });
1455
+ } else {
1456
+ console.warn("Cannot find column ".concat(from, " or column ").concat(to));
1457
+ }
1458
+ };
1459
+
1460
+ for (var _i = 0; _i < groups.length; _i++) {
1461
+ _loop(_i);
1462
+ }
1463
+ }
1464
+
1465
+ if (canGroupByRows) {
1466
+ var range = [];
1467
+ var prev = -2;
1468
+ var ok = true;
1469
+ self.selections.forEach(function (row, index) {
1470
+ if (!ok) return;
1471
+
1472
+ if (prev < -1) {
1473
+ prev = index;
1474
+ range[0] = index;
1475
+ return;
1476
+ }
1477
+
1478
+ if (index !== prev + 1 || !row || row.length === 0) {
1479
+ ok = false;
1480
+ return;
1481
+ }
1482
+
1483
+ prev = index;
1484
+ range[1] = index;
1485
+ });
1486
+ var rangeTitle = range.map(function (rowIndex) {
1487
+ var index = self.getBoundRowIndexFromViewRowIndex(rowIndex);
1488
+ if (typeof index === 'number') return index + 1;
1489
+ return rowIndex + 1;
1490
+ }).join('-');
1491
+
1492
+ if (ok && range.length === 2 && self.isNewGroupRangeValid(self.groupedRows, range[0], range[1])) {
1493
+ e.items.push({
1494
+ title: self.attributes.showGroupRows.replace('%s', rangeTitle),
1495
+ click: function click(ev) {
1496
+ ev.preventDefault();
1497
+ self.groupRows(range[0], range[1]);
1498
+ }
1499
+ });
1500
+ }
1278
1501
  }
1502
+
1503
+ if (canUngroupRows) {
1504
+ var rowIndex = e.cell.rowIndex;
1505
+
1506
+ var _groups = self.getGroupsRowBelongsTo(rowIndex);
1507
+
1508
+ var _loop2 = function _loop2(_i2) {
1509
+ var _groups$_i2 = _groups[_i2],
1510
+ from = _groups$_i2.from,
1511
+ to = _groups$_i2.to;
1512
+ var rangeTitle = [from, to].map(function (rowIndex) {
1513
+ var index = self.getBoundRowIndexFromViewRowIndex(rowIndex);
1514
+ if (typeof index === 'number') return index + 1;
1515
+ return rowIndex + 1;
1516
+ }).join('-');
1517
+ e.items.push({
1518
+ title: self.attributes.showRemoveGroupRows.replace('%s', rangeTitle),
1519
+ click: function click(ev) {
1520
+ ev.preventDefault();
1521
+ self.removeGroupRows(from, to);
1522
+ self.controlInput.focus();
1523
+ }
1524
+ });
1525
+ };
1526
+
1527
+ for (var _i2 = 0; _i2 < _groups.length; _i2++) {
1528
+ _loop2(_i2);
1529
+ }
1530
+ } //#endregion group/ungroup columns
1531
+
1279
1532
  }
1280
1533
 
1281
1534
  self.disposeAutocomplete = function () {
@@ -1306,6 +1559,59 @@ function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "functi
1306
1559
  self.contextmenuEvent = function (e, overridePos) {
1307
1560
  if (!self.hasFocus && e.target !== self.canvas) {
1308
1561
  return;
1562
+ } // don't create context menu for parents if current position is located in child grid
1563
+
1564
+
1565
+ var children = Object.keys(self.childGrids);
1566
+
1567
+ for (var i = 0; i < children.length; i++) {
1568
+ var childGrid = self.childGrids[children[i]];
1569
+ var parentNode = childGrid && childGrid.parentNode;
1570
+ if (!parentNode) continue;
1571
+ var offsetLeft = parentNode.offsetLeft,
1572
+ offsetWidth = parentNode.offsetWidth,
1573
+ offsetTop = parentNode.offsetTop,
1574
+ offsetHeight = parentNode.offsetHeight;
1575
+ if ((e.x >= offsetLeft && e.x <= offsetLeft + offsetWidth) === false) continue;
1576
+ if ((e.y >= offsetTop && e.y <= offsetTop + offsetHeight) === false) continue;
1577
+ return; // in child grid
1578
+ } // don't create context menu for child if current position is located in parent grid
1579
+
1580
+
1581
+ if (self.isChildGrid && self.parentNode) {
1582
+ //#region check is current child grid closed
1583
+ var childGridsOfParent = self.parentGrid && self.parentGrid.childGrids;
1584
+ if (!childGridsOfParent || !Array.isArray(childGridsOfParent)) return;
1585
+ var matchedMe = childGridsOfParent.find(function (grid) {
1586
+ var nodeA = grid.parentNode;
1587
+ var nodeB = self.parentNode;
1588
+ return nodeA.offsetTop == nodeB.offsetTop && nodeA.offsetLeft === nodeB.offsetLeft;
1589
+ });
1590
+ if (!matchedMe) return; //#endregion
1591
+
1592
+ var x0 = self.parentNode.offsetLeft;
1593
+ var x1 = self.parentNode.offsetLeft + self.parentNode.offsetWidth;
1594
+ var y0 = self.parentNode.offsetTop;
1595
+ var y1 = self.parentNode.offsetTop + self.parentNode.offsetHeight;
1596
+ var node = self.parentNode.parentNode;
1597
+
1598
+ while (node) {
1599
+ var _node = node,
1600
+ _offsetLeft = _node.offsetLeft,
1601
+ _offsetWidth = _node.offsetWidth,
1602
+ _offsetTop = _node.offsetTop,
1603
+ _offsetHeight = _node.offsetHeight;
1604
+ if (_offsetLeft > x0) x0 = _offsetLeft;
1605
+ if (_offsetTop > y0) y0 = _offsetTop;
1606
+ var newX1 = _offsetLeft + _offsetWidth;
1607
+ var newY1 = _offsetTop + _offsetHeight;
1608
+ if (newX1 < x1) x1 = newX1;
1609
+ if (newY1 < y1) y1 = newY1;
1610
+ if (node.nodeType !== 'canvas-datagrid-tree') break;
1611
+ node = node.parentNode;
1612
+ }
1613
+
1614
+ if ((e.x >= x0 && e.x <= x1 && e.y >= y0 && e.y <= y1) === false) return;
1309
1615
  }
1310
1616
 
1311
1617
  function createDisposeEvent() {
@@ -1321,6 +1627,7 @@ function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "functi
1321
1627
  ev = {
1322
1628
  NativeEvent: e,
1323
1629
  cell: self.getCellAt(pos.x, pos.y),
1630
+ pos: pos,
1324
1631
  items: items
1325
1632
  };
1326
1633
 
@@ -1394,8 +1701,10 @@ __webpack_require__.r(__webpack_exports__);
1394
1701
 
1395
1702
  /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(self) {
1396
1703
  self.defaults = {
1397
- attributes: [['allowColumnReordering', true], ['allowColumnResize', true], ['allowColumnResizeFromCell', false], ['allowFreezingRows', false], ['allowFreezingColumns', false], ['allowMovingSelection', true], ['allowRowHeaderResize', true], ['allowRowReordering', false], ['allowRowResize', true], ['allowRowResizeFromCell', false], ['allowSorting', true], ['animationDurationShowContextMenu', 50], ['animationDurationHideContextMenu', 50], ['autoGenerateSchema', false], ['autoResizeColumns', false], ['autoResizeRows', false], ['autoScrollOnMousemove', false], ['autoScrollMargin', 5], ['blanksText', '(Blanks)'], ['borderDragBehavior', 'none'], ['borderResizeZone', 10], ['clearSettingsOptionText', 'Clear saved settings'], ['columnHeaderClickBehavior', 'sort'], ['columnSelectorHiddenText', '&nbsp;&nbsp;&nbsp;'], ['columnSelectorText', 'Add/Remove columns'], ['columnSelectorVisibleText', "\u2713"], ['contextHoverScrollAmount', 2], ['contextHoverScrollRateMs', 5], ['copyHeadersOnSelectAll', true], ['copyText', 'Copy'], ['debug', false], ['editable', true], ['ellipsisText', '...'], ['filterOptionText', 'Filter %s'], ['filterTextPrefix', '(filtered) '], ['filterFrozenRows', true], ['globalRowResize', false], ['hideColumnText', 'Hide %s'], ['hoverMode', 'cell'], ['keepFocusOnMouseOut', false], ['maxAutoCompleteItems', 200], ['multiLine', false], ['name', ''], ['pageUpDownOverlap', 1], ['pasteText', 'Paste'], ['persistantSelectionMode', false], ['removeFilterOptionText', 'Remove filter on %s'], ['reorderDeadZone', 3], ['resizeScrollZone', 20], ['rowGrabZoneSize', 5], ['saveAppearance', true], ['scrollAnimationPPSThreshold', 0.75], ['scrollPointerLock', false], ['scrollRepeatRate', 75], ['selectionFollowsActiveCell', false], ['selectionHandleBehavior', 'none'], ['selectionMode', 'cell'], ['selectionScrollIncrement', 20], ['selectionScrollZone', 20], ['showClearSettingsOption', true], ['showColumnHeaders', true], ['showColumnSelector', true], ['showCopy', false], ['showFilter', true], ['showFilterInCell', false], ['showNewRow', false], ['showOrderByOption', true], ['showOrderByOptionTextAsc', 'Order by %s ascending'], ['showOrderByOptionTextDesc', 'Order by %s descending'], ['showPaste', false], ['showPerformance', false], ['showRowHeaders', true], ['showRowNumbers', true], ['showRowNumberGaps', true], ['singleSelectionMode', false], ['snapToRow', false], ['sortFrozenRows', true], ['touchContextMenuTimeMs', 800], ['touchDeadZone', 3], ['touchEasingMethod', 'easeOutQuad'], ['touchReleaseAcceleration', 1000], ['touchReleaseAnimationDurationMs', 2000], ['touchScrollZone', 20], ['touchSelectHandleZone', 20], ['touchZoomSensitivity', 0.005], ['touchZoomMin', 0.5], ['touchZoomMax', 1.75], ['maxPixelRatio', 2], ['tree', false], ['treeHorizontalScroll', false]],
1398
- styles: [['activeCellBackgroundColor', 'rgba(255, 255, 255, 1)'], ['activeCellBorderColor', 'rgba(110, 168, 255, 1)'], ['activeCellBorderWidth', 1], ['activeCellColor', 'rgba(0, 0, 0, 1)'], ['activeCellFont', '16px sans-serif'], ['activeCellHoverBackgroundColor', 'rgba(255, 255, 255, 1)'], ['activeCellHorizontalAlignment', 'left'], ['activeCellHoverColor', 'rgba(0, 0, 0, 1)'], ['activeCellOverlayBorderColor', 'rgba(66, 133, 244, 1)'], ['activeCellOverlayBorderWidth', 1], ['activeCellPaddingBottom', 5], ['activeCellPaddingLeft', 5], ['activeCellPaddingRight', 5], ['activeCellPaddingTop', 5], ['activeCellSelectedBackgroundColor', 'rgba(236, 243, 255, 1)'], ['activeCellSelectedColor', 'rgba(0, 0, 0, 1)'], ['activeCellVerticalAlignment', 'center'], ['activeColumnHeaderCellBackgroundColor', 'rgba(225, 225, 225, 1)'], ['activeColumnHeaderCellColor', 'rgba(0, 0, 0, 1)'], ['activeRowHeaderCellBackgroundColor', 'rgba(225, 225, 225, 1)'], ['activeRowHeaderCellColor', 'rgba(0, 0, 0, 1)'], ['autocompleteBottomMargin', 60], ['autosizeHeaderCellPadding', 8], ['autosizePadding', 5], ['buttonActiveBackgroundColor', 'rgba(255, 255, 255, 1)'], ['buttonActiveBorderColor', 'rgba(110, 168, 255, 1)'], ['buttonArrowColor', 'rgba(50, 50, 50, 1)'], ['buttonArrowDownHTML', '&#x25BC;'], ['buttonZIndex', 10000], ['buttonBackgroundColor', 'rgba(255, 255, 255, 1)'], ['buttonBorderColor', 'rgba(172, 172, 172, 1)'], ['buttonHoverBackgroundColor', 'rgba(240, 240, 240, 1)'], ['buttonMenuWindowMargin', 30], ['buttonPadding', '3px'], ['cellAutoResizePadding', 13], ['cellBackgroundColor', 'rgba(255, 255, 255, 1)'], ['cellBorderColor', 'rgba(195, 199, 202, 1)'], ['cellBorderWidth', 1], ['cellColor', 'rgba(0, 0, 0, 1)'], ['cellFont', '16px sans-serif'], ['cellGridHeight', 250], ['cellHeight', 24], ['cellHeightWithChildGrid', 150], ['cellHorizontalAlignment', 'left'], ['cellHoverBackgroundColor', 'rgba(255, 255, 255, 1)'], ['cellHoverColor', 'rgba(0, 0, 0, 1)'], ['cellPaddingBottom', 5], ['cellPaddingLeft', 5], ['cellPaddingRight', 5], ['cellPaddingTop', 5], ['cellSelectedBackgroundColor', 'rgba(236, 243, 255, 1)'], ['cellSelectedColor', 'rgba(0, 0, 0, 1)'], ['cellVerticalAlignment', 'center'], ['cellWidth', 250], ['cellWidthWithChildGrid', 250], ['cellWhiteSpace', 'nowrap'], ['cellLineHeight', 1], ['cellLineSpacing', 3], ['childContextMenuArrowColor', 'rgba(43, 48, 43, 1)'], ['childContextMenuArrowHTML', '&#x25BA;'], ['childContextMenuMarginLeft', -11], ['childContextMenuMarginTop', -6], ['columnHeaderCellBackgroundColor', 'rgba(240, 240, 240, 1)'], ['columnHeaderCellBorderColor', 'rgba(172, 172, 172, 1)'], ['columnHeaderCellBorderWidth', 1], ['columnHeaderCellCapBackgroundColor', 'rgba(240, 240, 240, 1)'], ['columnHeaderCellCapBorderColor', 'rgba(172, 172, 172, 1)'], ['columnHeaderCellCapBorderWidth', 1], ['columnHeaderCellColor', 'rgba(50, 50, 50, 1)'], ['columnHeaderCellFont', '16px sans-serif'], ['columnHeaderCellHeight', 25], ['columnHeaderCellHorizontalAlignment', 'left'], ['columnHeaderCellHoverBackgroundColor', 'rgba(235, 235, 235, 1)'], ['columnHeaderCellHoverColor', 'rgba(0, 0, 0, 1)'], ['columnHeaderCellPaddingBottom', 5], ['columnHeaderCellPaddingLeft', 5], ['columnHeaderCellPaddingRight', 5], ['columnHeaderCellPaddingTop', 5], ['columnHeaderCellVerticalAlignment', 'center'], ['columnHeaderOrderByArrowBorderColor', 'rgba(195, 199, 202, 1)'], ['columnHeaderOrderByArrowBorderWidth', 1], ['columnHeaderOrderByArrowColor', 'rgba(155, 155, 155, 1)'], ['columnHeaderOrderByArrowHeight', 8], ['columnHeaderOrderByArrowMarginLeft', 0], ['columnHeaderOrderByArrowMarginRight', 5], ['columnHeaderOrderByArrowMarginTop', 6], ['columnHeaderOrderByArrowWidth', 13], ['contextFilterButtonBorder', 'solid 1px rgba(158, 163, 169, 1)'], ['contextFilterButtonBorderRadius', '3px'], ['contextFilterButtonHTML', '&#x25BC;'], ['contextFilterInputBackground', 'rgba(255,255,255,1)'], ['contextFilterInputBorder', 'solid 1px rgba(158, 163, 169, 1)'], ['contextFilterInputBorderRadius', '0'], ['contextFilterInputColor', 'rgba(0,0,0,1)'], ['contextFilterInputFontFamily', 'sans-serif'], ['contextFilterInputFontSize', '14px'], ['contextFilterInvalidRegExpBackground', 'rgba(180, 6, 1, 1)'], ['contextFilterInvalidRegExpColor', 'rgba(255, 255, 255, 1)'], ['contextMenuArrowColor', 'rgba(43, 48, 43, 1)'], ['contextMenuArrowDownHTML', '&#x25BC;'], ['contextMenuArrowUpHTML', '&#x25B2;'], ['contextMenuBackground', 'rgba(240, 240, 240, 1)'], ['contextMenuBorder', 'solid 1px rgba(158, 163, 169, 1)'], ['contextMenuBorderRadius', '3px'], ['contextMenuChildArrowFontSize', '12px'], ['contextMenuColor', 'rgba(43, 48, 43, 1)'], ['contextMenuCursor', 'default'], ['contextMenuFilterButtonFontFamily', 'sans-serif'], ['contextMenuFilterButtonFontSize', '10px'], ['contextMenuFilterInvalidExpresion', 'rgba(237, 155, 156, 1)'], ['contextMenuFontFamily', 'sans-serif'], ['contextMenuFontSize', '16px'], ['contextMenuHoverBackground', 'rgba(182, 205, 250, 1)'], ['contextMenuHoverColor', 'rgba(43, 48, 153, 1)'], ['contextMenuItemBorderRadius', '3px'], ['contextMenuItemMargin', '2px'], ['contextMenuLabelDisplay', 'inline-block'], ['contextMenuLabelMargin', '0 3px 0 0'], ['contextMenuLabelMaxWidth', '700px'], ['contextMenuLabelMinWidth', '75px'], ['contextMenuMarginLeft', 3], ['contextMenuMarginTop', -3], ['contextMenuOpacity', '0.98'], ['contextMenuPadding', '2px'], ['contextMenuWindowMargin', 30], ['contextMenuZIndex', 10000], ['cornerCellBackgroundColor', 'rgba(240, 240, 240, 1)'], ['cornerCellBorderColor', 'rgba(202, 202, 202, 1)'], ['debugBackgroundColor', 'rgba(0, 0, 0, .0)'], ['debugColor', 'rgba(255, 15, 24, 1)'], ['debugEntitiesColor', 'rgba(76, 231, 239, 1.00)'], ['debugFont', '11px sans-serif'], ['debugPerfChartBackground', 'rgba(29, 25, 26, 1.00)'], ['debugPerfChartTextColor', 'rgba(255, 255, 255, 0.8)'], ['debugPerformanceColor', 'rgba(252, 255, 37, 1.00)'], ['debugScrollHeightColor', 'rgba(248, 33, 103, 1.00)'], ['debugScrollWidthColor', 'rgba(66, 255, 27, 1.00)'], ['debugTouchPPSXColor', 'rgba(246, 102, 24, 1.00)'], ['debugTouchPPSYColor', 'rgba(186, 0, 255, 1.00)'], ['display', 'inline-block'], ['editCellBackgroundColor', 'white'], ['editCellBorder', 'solid 1px rgba(110, 168, 255, 1)'], ['editCellBoxShadow', '0 2px 5px rgba(0,0,0,0.4)'], ['editCellColor', 'black'], ['editCellFontFamily', 'sans-serif'], ['editCellFontSize', '16px'], ['editCellPaddingLeft', 4], ['editCellZIndex', 10000], ['filterButtonActiveBackgroundColor', 'rgba(225, 225, 225, 1)'], ['filterButtonArrowBorderColor', 'rgba(195, 199, 202, 1)'], ['filterButtonArrowBorderWidth', 1], ['filterButtonArrowClickRadius', 5], ['filterButtonArrowColor', 'rgba(50, 50, 50, 1)'], ['filterButtonArrowHeight', 5], ['filterButtonArrowWidth', 8], ['filterButtonBackgroundColor', 'rgba(240, 240, 240, 1)'], ['filterButtonBorderColor', 'rgba(172, 172, 172, 1)'], ['filterButtonBorderRadius', 3], ['filterButtonHeight', 20], ['filterButtonHoverBackgroundColor', 'rgba(235, 235, 235, 1)'], ['filterButtonMenuOffsetTop', 10], ['filterButtonWidth', 20], ['frozenMarkerHoverColor', 'rgba(236, 243, 255, 1)'], ['frozenMarkerHoverBorderColor', 'rgba(110, 168, 255, 1)'], ['frozenMarkerActiveColor', 'rgba(236, 243, 255, 1)'], ['frozenMarkerActiveBorderColor', 'rgba(110, 168, 255, 1)'], ['frozenMarkerColor', 'rgba(222, 222, 222, 1)'], ['frozenMarkerBorderColor', 'rgba(168, 168, 168, 1)'], ['frozenMarkerBorderWidth', 1], ['frozenMarkerWidth', 2], ['gridBackgroundColor', 'rgba(240, 240, 240, 1)'], ['gridBorderCollapse', 'collapse'], ['gridBorderColor', 'rgba(202, 202, 202, 1)'], ['gridBorderWidth', 1], ['height', 'auto'], ['maxHeight', 'inherit'], ['maxWidth', 'inherit'], ['minColumnWidth', 45], ['minHeight', 'inherit'], ['minRowHeight', 24], ['minWidth', 'inherit'], ['mobileContextMenuMargin', 10], ['mobileEditInputHeight', 30], ['mobileEditFontFamily', 'sans-serif'], ['mobileEditFontSize', '16px'], ['moveOverlayBorderWidth', 1], ['moveOverlayBorderColor', 'rgba(66, 133, 244, 1)'], ['moveOverlayBorderSegments', '12, 7'], ['name', 'default'], ['overflowY', 'auto'], ['overflowX', 'auto'], ['reorderMarkerBackgroundColor', 'rgba(0, 0, 0, 0.1)'], ['reorderMarkerBorderColor', 'rgba(0, 0, 0, 0.2)'], ['reorderMarkerBorderWidth', 1.25], ['reorderMarkerIndexBorderColor', 'rgba(66, 133, 244, 1)'], ['reorderMarkerIndexBorderWidth', 2.75], ['rowHeaderCellBackgroundColor', 'rgba(240, 240, 240, 1)'], ['rowHeaderCellBorderColor', 'rgba(200, 200, 200, 1)'], ['rowHeaderCellBorderWidth', 1], ['rowHeaderCellColor', 'rgba(50, 50, 50, 1)'], ['rowHeaderCellFont', '16px sans-serif'], ['rowHeaderCellHeight', 25], ['rowHeaderCellHorizontalAlignment', 'left'], ['rowHeaderCellHoverBackgroundColor', 'rgba(235, 235, 235, 1)'], ['rowHeaderCellHoverColor', 'rgba(0, 0, 0, 1)'], ['rowHeaderCellPaddingBottom', 5], ['rowHeaderCellPaddingLeft', 5], ['rowHeaderCellPaddingRight', 5], ['rowHeaderCellPaddingTop', 5], ['rowHeaderCellRowNumberGapHeight', 5], ['rowHeaderCellRowNumberGapColor', 'rgba(50, 50, 50, 1)'], ['rowHeaderCellSelectedBackgroundColor', 'rgba(217, 217, 217, 1)'], ['rowHeaderCellSelectedColor', 'rgba(50, 50, 50, 1)'], ['rowHeaderCellVerticalAlignment', 'center'], ['rowHeaderCellWidth', 57], ['scrollBarActiveColor', 'rgba(125, 125, 125, 1)'], ['scrollBarBackgroundColor', 'rgba(240, 240, 240, 1)'], ['scrollBarBorderColor', 'rgba(202, 202, 202, 1)'], ['scrollBarBorderWidth', 0.5], ['scrollBarBoxBorderRadius', 4.125], ['scrollBarBoxColor', 'rgba(192, 192, 192, 1)'], ['scrollBarBoxMargin', 2], ['scrollBarBoxMinSize', 15], ['scrollBarBoxWidth', 8], ['scrollBarCornerBackgroundColor', 'rgba(240, 240, 240, 1)'], ['scrollBarCornerBorderColor', 'rgba(202, 202, 202, 1)'], ['scrollBarWidth', 11], ['selectionHandleBorderColor', 'rgba(255, 255, 255, 1)'], ['selectionHandleBorderWidth', 1.5], ['selectionHandleColor', 'rgba(66, 133, 244, 1)'], ['selectionHandleSize', 8], ['selectionHandleType', 'square'], ['selectionOverlayBorderColor', 'rgba(66, 133, 244, 1)'], ['selectionOverlayBorderWidth', 1], ['treeArrowBorderColor', 'rgba(195, 199, 202, 1)'], ['treeArrowBorderWidth', 1], ['treeArrowClickRadius', 5], ['treeArrowColor', 'rgba(155, 155, 155, 1)'], ['treeArrowHeight', 8], ['treeArrowMarginLeft', 0], ['treeArrowMarginRight', 5], ['treeArrowMarginTop', 6], ['treeArrowWidth', 13], ['treeGridHeight', 250], ['width', 'auto']]
1704
+ attributes: [['allowColumnReordering', true], ['allowColumnResize', true], ['allowColumnResizeFromCell', false], ['allowFreezingRows', false], ['allowFreezingColumns', false], ['allowMovingSelection', true], ['allowRowHeaderResize', true], ['allowRowReordering', false], ['allowRowResize', true], ['allowRowResizeFromCell', false], ['allowSorting', true], ['allowGroupingRows', true], ['allowGroupingColumns', true], ['animationDurationShowContextMenu', 50], ['animationDurationHideContextMenu', 50], ['autoGenerateSchema', false], ['autoResizeColumns', false], ['autoResizeRows', false], ['autoScrollOnMousemove', false], ['autoScrollMargin', 5], ['blanksText', '(Blanks)'], ['borderDragBehavior', 'none'], ['borderResizeZone', 10], ['clearSettingsOptionText', 'Clear saved settings'], ['columnHeaderClickBehavior', 'sort'], ['columnSelectorHiddenText', '&nbsp;&nbsp;&nbsp;'], ['columnSelectorText', 'Add/Remove columns'], ['columnSelectorVisibleText', "\u2713"], ['contextHoverScrollAmount', 2], ['contextHoverScrollRateMs', 5], ['copyHeadersOnSelectAll', true], ['copyText', 'Copy'], ['debug', false], ['editable', true], ['ellipsisText', '...'], ['filterOptionText', 'Filter %s'], ['filterTextPrefix', '(filtered) '], ['filterFrozenRows', true], ['globalRowResize', false], ['hideColumnText', 'Hide %s'], ['hoverMode', 'cell'], ['keepFocusOnMouseOut', false], ['maxAutoCompleteItems', 200], ['multiLine', false], ['name', ''], ['pageUpDownOverlap', 1], ['pasteText', 'Paste'], ['persistantSelectionMode', false], ['removeFilterOptionText', 'Remove filter on %s'], ['reorderDeadZone', 3], ['resizeScrollZone', 20], ['rowGrabZoneSize', 5], ['columnGrabZoneSize', 30], ['saveAppearance', true], ['scrollAnimationPPSThreshold', 0.75], ['scrollPointerLock', false], ['scrollRepeatRate', 75], ['selectionFollowsActiveCell', false], ['selectionHandleBehavior', 'none'], ['selectionMode', 'cell'], ['selectionScrollIncrement', 20], ['selectionScrollZone', 20], ['showClearSettingsOption', true], ['showColumnHeaders', true], ['showColumnSelector', true], ['showCopy', false], ['showFilter', true], ['showFilterInCell', false], ['showNewRow', false], ['showOrderByOption', true], ['showOrderByOptionTextAsc', 'Order by %s ascending'], ['showOrderByOptionTextDesc', 'Order by %s descending'], //#region grouping
1705
+ ['showGroupColumns', 'Group columns %s'], ['showGroupRows', 'Group rows %s'], ['showRemoveGroupColumns', 'Remove group %s'], ['showRemoveGroupRows', 'Remove group %s'], ['showRemoveAllGroupColumns', 'Remove all column groups'], ['showRemoveAllGroupRows', 'Remove all row groups'], ['showExpandAllGroupColumns', 'Expand all column groups'], ['showExpandAllGroupRows', 'Expand all row groups'], ['showCollapseAllGroupColumns', 'Collapse all column groups'], ['showCollapseAllGroupRows', 'Collapse all row groups'], ['columnGroupIndicatorPosition', 'right'], ['rowGroupIndicatorPosition', 'bottom'], //#endregion grouping
1706
+ ['showPaste', false], ['showPerformance', false], ['showRowHeaders', true], ['showRowNumbers', true], ['showRowNumberGaps', true], ['singleSelectionMode', false], ['snapToRow', false], ['sortFrozenRows', true], ['touchContextMenuTimeMs', 800], ['touchDeadZone', 3], ['touchEasingMethod', 'easeOutQuad'], ['touchReleaseAcceleration', 1000], ['touchReleaseAnimationDurationMs', 2000], ['touchScrollZone', 20], ['touchSelectHandleZone', 20], ['touchZoomSensitivity', 0.005], ['touchZoomMin', 0.5], ['touchZoomMax', 1.75], ['maxPixelRatio', 2], ['tree', false], ['treeHorizontalScroll', false], ['rowTree', []], ['rowTreeColIndex', 0], ['columnTree', []], ['columnTreeRowStartIndex', 0], ['columnTreeRowEndIndex', 0]],
1707
+ styles: [['activeCellBackgroundColor', 'rgba(255, 255, 255, 1)'], ['activeCellBorderColor', 'rgba(110, 168, 255, 1)'], ['activeCellBorderWidth', 1], ['activeCellColor', 'rgba(0, 0, 0, 1)'], ['activeCellFont', '16px sans-serif'], ['activeCellHoverBackgroundColor', 'rgba(255, 255, 255, 1)'], ['activeCellHorizontalAlignment', 'left'], ['activeCellHoverColor', 'rgba(0, 0, 0, 1)'], ['activeCellOverlayBorderColor', 'rgba(66, 133, 244, 1)'], ['activeCellOverlayBorderWidth', 1], ['activeCellPaddingBottom', 5], ['activeCellPaddingLeft', 5], ['activeCellPaddingRight', 5], ['activeCellPaddingTop', 5], ['activeCellSelectedBackgroundColor', 'rgba(236, 243, 255, 1)'], ['activeCellSelectedColor', 'rgba(0, 0, 0, 1)'], ['activeCellVerticalAlignment', 'center'], ['activeColumnHeaderCellBackgroundColor', 'rgba(225, 225, 225, 1)'], ['activeColumnHeaderCellColor', 'rgba(0, 0, 0, 1)'], ['activeRowHeaderCellBackgroundColor', 'rgba(225, 225, 225, 1)'], ['activeRowHeaderCellColor', 'rgba(0, 0, 0, 1)'], ['autocompleteBottomMargin', 60], ['autosizeHeaderCellPadding', 8], ['autosizePadding', 5], ['buttonActiveBackgroundColor', 'rgba(255, 255, 255, 1)'], ['buttonActiveBorderColor', 'rgba(110, 168, 255, 1)'], ['buttonArrowColor', 'rgba(50, 50, 50, 1)'], ['buttonArrowDownHTML', '&#x25BC;'], ['buttonZIndex', 10000], ['buttonBackgroundColor', 'rgba(255, 255, 255, 1)'], ['buttonBorderColor', 'rgba(172, 172, 172, 1)'], ['buttonHoverBackgroundColor', 'rgba(240, 240, 240, 1)'], ['buttonMenuWindowMargin', 30], ['buttonPadding', '3px'], ['cellAutoResizePadding', 13], ['cellBackgroundColor', 'rgba(255, 255, 255, 1)'], ['cellBorderColor', 'rgba(195, 199, 202, 1)'], ['cellBorderWidth', 1], ['cellColor', 'rgba(0, 0, 0, 1)'], ['cellFont', '16px sans-serif'], ['cellGridHeight', 250], ['cellHeight', 24], ['cellHeightWithChildGrid', 150], ['cellHorizontalAlignment', 'left'], ['cellHoverBackgroundColor', 'rgba(255, 255, 255, 1)'], ['cellHoverColor', 'rgba(0, 0, 0, 1)'], ['cellPaddingBottom', 5], ['cellPaddingLeft', 5], ['cellPaddingRight', 5], ['cellPaddingTop', 5], ['cellSelectedBackgroundColor', 'rgba(236, 243, 255, 1)'], ['cellSelectedColor', 'rgba(0, 0, 0, 1)'], ['cellTreeIconBorderColor', 'rgba(162, 174, 207, 1)'], ['cellTreeIconFillColor', 'rgba(240, 240, 240, 1)'], ['cellTreeIconHoverFillColor', 'rgba(198, 217, 233, 1)'], ['cellTreeIconLineColor', 'rgba(43, 53, 81, 1)'], ['cellTreeIconLineWidth', 1.5], ['cellTreeIconMarginLeft', 0], ['cellTreeIconMarginRight', 5], ['cellTreeIconMarginTop', 6], ['cellTreeIconWidth', 13], ['cellVerticalAlignment', 'center'], ['cellWidth', 250], ['cellWidthWithChildGrid', 250], ['cellWhiteSpace', 'nowrap'], ['cellLineHeight', 1], ['cellLineSpacing', 3], ['childContextMenuArrowColor', 'rgba(43, 48, 43, 1)'], ['childContextMenuArrowHTML', '&#x25BA;'], ['childContextMenuMarginLeft', -11], ['childContextMenuMarginTop', -6], ['columnGroupRowHeight', 25], ['columnHeaderCellBackgroundColor', 'rgba(240, 240, 240, 1)'], ['columnHeaderCellBorderColor', 'rgba(172, 172, 172, 1)'], ['columnHeaderCellBorderWidth', 1], ['columnHeaderCellCapBackgroundColor', 'rgba(240, 240, 240, 1)'], ['columnHeaderCellCapBorderColor', 'rgba(172, 172, 172, 1)'], ['columnHeaderCellCapBorderWidth', 1], ['columnHeaderCellColor', 'rgba(50, 50, 50, 1)'], ['columnHeaderCellFont', '16px sans-serif'], ['columnHeaderCellHeight', 25], ['columnHeaderCellHorizontalAlignment', 'left'], ['columnHeaderCellHoverBackgroundColor', 'rgba(235, 235, 235, 1)'], ['columnHeaderCellHoverColor', 'rgba(0, 0, 0, 1)'], ['columnHeaderCellPaddingBottom', 5], ['columnHeaderCellPaddingLeft', 5], ['columnHeaderCellPaddingRight', 5], ['columnHeaderCellPaddingTop', 5], ['columnHeaderCellVerticalAlignment', 'center'], ['columnHeaderOrderByArrowBorderColor', 'rgba(195, 199, 202, 1)'], ['columnHeaderOrderByArrowBorderWidth', 1], ['columnHeaderOrderByArrowColor', 'rgba(155, 155, 155, 1)'], ['columnHeaderOrderByArrowHeight', 8], ['columnHeaderOrderByArrowMarginLeft', 0], ['columnHeaderOrderByArrowMarginRight', 5], ['columnHeaderOrderByArrowMarginTop', 6], ['columnHeaderOrderByArrowWidth', 13], ['contextFilterButtonBorder', 'solid 1px rgba(158, 163, 169, 1)'], ['contextFilterButtonBorderRadius', '3px'], ['contextFilterButtonHTML', '&#x25BC;'], ['contextFilterInputBackground', 'rgba(255,255,255,1)'], ['contextFilterInputBorder', 'solid 1px rgba(158, 163, 169, 1)'], ['contextFilterInputBorderRadius', '0'], ['contextFilterInputColor', 'rgba(0,0,0,1)'], ['contextFilterInputFontFamily', 'sans-serif'], ['contextFilterInputFontSize', '14px'], ['contextFilterInvalidRegExpBackground', 'rgba(180, 6, 1, 1)'], ['contextFilterInvalidRegExpColor', 'rgba(255, 255, 255, 1)'], ['contextMenuArrowColor', 'rgba(43, 48, 43, 1)'], ['contextMenuArrowDownHTML', '&#x25BC;'], ['contextMenuArrowUpHTML', '&#x25B2;'], ['contextMenuBackground', 'rgba(240, 240, 240, 1)'], ['contextMenuBorder', 'solid 1px rgba(158, 163, 169, 1)'], ['contextMenuBorderRadius', '3px'], ['contextMenuChildArrowFontSize', '12px'], ['contextMenuColor', 'rgba(43, 48, 43, 1)'], ['contextMenuCursor', 'default'], ['contextMenuFilterButtonFontFamily', 'sans-serif'], ['contextMenuFilterButtonFontSize', '10px'], ['contextMenuFilterInvalidExpresion', 'rgba(237, 155, 156, 1)'], ['contextMenuFontFamily', 'sans-serif'], ['contextMenuFontSize', '16px'], ['contextMenuHoverBackground', 'rgba(182, 205, 250, 1)'], ['contextMenuHoverColor', 'rgba(43, 48, 153, 1)'], ['contextMenuItemBorderRadius', '3px'], ['contextMenuItemMargin', '2px'], ['contextMenuLabelDisplay', 'inline-block'], ['contextMenuLabelMargin', '0 3px 0 0'], ['contextMenuLabelMaxWidth', '700px'], ['contextMenuLabelMinWidth', '75px'], ['contextMenuMarginLeft', 3], ['contextMenuMarginTop', -3], ['contextMenuOpacity', '0.98'], ['contextMenuPadding', '2px'], ['contextMenuWindowMargin', 30], ['contextMenuZIndex', 10000], ['cornerCellBackgroundColor', 'rgba(240, 240, 240, 1)'], ['cornerCellBorderColor', 'rgba(202, 202, 202, 1)'], ['debugBackgroundColor', 'rgba(0, 0, 0, .0)'], ['debugColor', 'rgba(255, 15, 24, 1)'], ['debugEntitiesColor', 'rgba(76, 231, 239, 1.00)'], ['debugFont', '11px sans-serif'], ['debugPerfChartBackground', 'rgba(29, 25, 26, 1.00)'], ['debugPerfChartTextColor', 'rgba(255, 255, 255, 0.8)'], ['debugPerformanceColor', 'rgba(252, 255, 37, 1.00)'], ['debugScrollHeightColor', 'rgba(248, 33, 103, 1.00)'], ['debugScrollWidthColor', 'rgba(66, 255, 27, 1.00)'], ['debugTouchPPSXColor', 'rgba(246, 102, 24, 1.00)'], ['debugTouchPPSYColor', 'rgba(186, 0, 255, 1.00)'], ['display', 'inline-block'], ['editCellBackgroundColor', 'white'], ['editCellBorder', 'solid 1px rgba(110, 168, 255, 1)'], ['editCellBoxShadow', '0 2px 5px rgba(0,0,0,0.4)'], ['editCellColor', 'black'], ['editCellFontFamily', 'sans-serif'], ['editCellFontSize', '16px'], ['editCellPaddingLeft', 4], ['editCellZIndex', 10000], ['filterButtonActiveBackgroundColor', 'rgba(225, 225, 225, 1)'], ['filterButtonArrowBorderColor', 'rgba(195, 199, 202, 1)'], ['filterButtonArrowBorderWidth', 1], ['filterButtonArrowClickRadius', 5], ['filterButtonArrowColor', 'rgba(50, 50, 50, 1)'], ['filterButtonArrowHeight', 5], ['filterButtonArrowWidth', 8], ['filterButtonBackgroundColor', 'rgba(240, 240, 240, 1)'], ['filterButtonBorderColor', 'rgba(172, 172, 172, 1)'], ['filterButtonBorderRadius', 3], ['filterButtonHeight', 20], ['filterButtonHoverBackgroundColor', 'rgba(235, 235, 235, 1)'], ['filterButtonMenuOffsetTop', 10], ['filterButtonWidth', 20], ['frozenMarkerHoverColor', 'rgba(236, 243, 255, 1)'], ['frozenMarkerHoverBorderColor', 'rgba(110, 168, 255, 1)'], ['frozenMarkerActiveColor', 'rgba(236, 243, 255, 1)'], ['frozenMarkerActiveBorderColor', 'rgba(110, 168, 255, 1)'], ['frozenMarkerColor', 'rgba(222, 222, 222, 1)'], ['frozenMarkerBorderColor', 'rgba(168, 168, 168, 1)'], ['frozenMarkerBorderWidth', 1], ['frozenMarkerWidth', 2], ['groupingAreaBackgroundColor', 'rgba(240, 240, 240, 1)'], ['gridBackgroundColor', 'rgba(240, 240, 240, 1)'], ['gridBorderCollapse', 'collapse'], ['gridBorderColor', 'rgba(202, 202, 202, 1)'], ['gridBorderWidth', 1], ['groupIndicatorColor', 'rgba(155, 155, 155, 1)'], ['groupIndicatorBackgroundColor', 'rgba(255, 255, 255, 1)'], ['height', 'auto'], ['maxHeight', 'inherit'], ['maxWidth', 'inherit'], ['minColumnWidth', 45], ['minHeight', 'inherit'], ['minRowHeight', 24], ['minWidth', 'inherit'], ['mobileContextMenuMargin', 10], ['mobileEditInputHeight', 30], ['mobileEditFontFamily', 'sans-serif'], ['mobileEditFontSize', '16px'], ['moveOverlayBorderWidth', 1], ['moveOverlayBorderColor', 'rgba(66, 133, 244, 1)'], ['moveOverlayBorderSegments', '12, 7'], ['name', 'default'], ['overflowY', 'auto'], ['overflowX', 'auto'], ['reorderMarkerBackgroundColor', 'rgba(0, 0, 0, 0.1)'], ['reorderMarkerBorderColor', 'rgba(0, 0, 0, 0.2)'], ['reorderMarkerBorderWidth', 1.25], ['reorderMarkerIndexBorderColor', 'rgba(66, 133, 244, 1)'], ['reorderMarkerIndexBorderWidth', 2.75], ['rowGroupColumnWidth', 25], ['rowHeaderCellBackgroundColor', 'rgba(240, 240, 240, 1)'], ['rowHeaderCellBorderColor', 'rgba(200, 200, 200, 1)'], ['rowHeaderCellBorderWidth', 1], ['rowHeaderCellColor', 'rgba(50, 50, 50, 1)'], ['rowHeaderCellFont', '16px sans-serif'], ['rowHeaderCellHeight', 25], ['rowHeaderCellHorizontalAlignment', 'left'], ['rowHeaderCellHoverBackgroundColor', 'rgba(235, 235, 235, 1)'], ['rowHeaderCellHoverColor', 'rgba(0, 0, 0, 1)'], ['rowHeaderCellPaddingBottom', 5], ['rowHeaderCellPaddingLeft', 5], ['rowHeaderCellPaddingRight', 5], ['rowHeaderCellPaddingTop', 5], ['rowHeaderCellRowNumberGapHeight', 5], ['rowHeaderCellRowNumberGapColor', 'rgba(50, 50, 50, 1)'], ['rowHeaderCellSelectedBackgroundColor', 'rgba(217, 217, 217, 1)'], ['rowHeaderCellSelectedColor', 'rgba(50, 50, 50, 1)'], ['rowHeaderCellVerticalAlignment', 'center'], ['rowHeaderCellWidth', 57], ['scrollBarActiveColor', 'rgba(125, 125, 125, 1)'], ['scrollBarBackgroundColor', 'rgba(240, 240, 240, 1)'], ['scrollBarBorderColor', 'rgba(202, 202, 202, 1)'], ['scrollBarBorderWidth', 0.5], ['scrollBarBoxBorderRadius', 4.125], ['scrollBarBoxColor', 'rgba(192, 192, 192, 1)'], ['scrollBarBoxMargin', 2], ['scrollBarBoxMinSize', 15], ['scrollBarBoxWidth', 8], ['scrollBarCornerBackgroundColor', 'rgba(240, 240, 240, 1)'], ['scrollBarCornerBorderColor', 'rgba(202, 202, 202, 1)'], ['scrollBarWidth', 11], ['selectionHandleBorderColor', 'rgba(255, 255, 255, 1)'], ['selectionHandleBorderWidth', 1.5], ['selectionHandleColor', 'rgba(66, 133, 244, 1)'], ['selectionHandleSize', 8], ['selectionHandleType', 'square'], ['selectionOverlayBorderColor', 'rgba(66, 133, 244, 1)'], ['selectionOverlayBorderWidth', 1], ['treeArrowBorderColor', 'rgba(195, 199, 202, 1)'], ['treeArrowBorderWidth', 1], ['treeArrowClickRadius', 5], ['treeArrowColor', 'rgba(155, 155, 155, 1)'], ['treeArrowHeight', 8], ['treeArrowMarginLeft', 0], ['treeArrowMarginRight', 5], ['treeArrowMarginTop', 6], ['treeArrowWidth', 13], ['treeGridHeight', 250], ['width', 'auto']]
1399
1708
  };
1400
1709
  }
1401
1710
 
@@ -1524,8 +1833,19 @@ __webpack_require__.r(__webpack_exports__);
1524
1833
  return;
1525
1834
  }
1526
1835
 
1527
- self.input.style.left = pos.left + cell.x + self.canvasOffsetLeft - s.left + 'px';
1528
- self.input.style.top = pos.top + cell.y - self.style.cellBorderWidth + self.canvasOffsetTop - s.top + 'px';
1836
+ var groupAreaOffsetY = self.getColumnGroupAreaHeight();
1837
+ var groupAreaOffsetX = self.getRowGroupAreaWidth();
1838
+
1839
+ if (self.parentNode) {
1840
+ var _self$parentNode = self.parentNode,
1841
+ columnGroupsAreaHeight = _self$parentNode.columnGroupsAreaHeight,
1842
+ rowGroupsAreaWidth = _self$parentNode.rowGroupsAreaWidth;
1843
+ if (columnGroupsAreaHeight) groupAreaOffsetY += columnGroupsAreaHeight;
1844
+ if (rowGroupsAreaWidth) groupAreaOffsetX += rowGroupsAreaWidth;
1845
+ }
1846
+
1847
+ self.input.style.left = pos.left + cell.x + self.canvasOffsetLeft - s.left + groupAreaOffsetX + 'px';
1848
+ self.input.style.top = pos.top + cell.y - self.style.cellBorderWidth + self.canvasOffsetTop - s.top + groupAreaOffsetY + 'px';
1529
1849
  self.input.style.height = cell.height - borderWidth + 'px';
1530
1850
  self.input.style.width = cell.width - self.style.cellPaddingLeft + 'px';
1531
1851
  self.clipElement(self.input);
@@ -1538,12 +1858,19 @@ __webpack_require__.r(__webpack_exports__);
1538
1858
  s = e,
1539
1859
  h,
1540
1860
  w;
1861
+ var calculatedTree = false;
1541
1862
 
1542
1863
  while (e.offsetParent && e.nodeName !== 'CANVAS-DATAGRID') {
1543
- x += e.offsetLeft;
1544
- y += e.offsetTop;
1545
- h = e.offsetHeight;
1546
- w = e.offsetWidth;
1864
+ var isTree = e.nodeType === 'canvas-datagrid-tree';
1865
+
1866
+ if (!isTree || !calculatedTree) {
1867
+ x += e.offsetLeft;
1868
+ y += e.offsetTop;
1869
+ h = e.offsetHeight;
1870
+ w = e.offsetWidth;
1871
+ }
1872
+
1873
+ if (isTree) calculatedTree = true;
1547
1874
  e = e.offsetParent;
1548
1875
  }
1549
1876
 
@@ -1576,6 +1903,8 @@ __webpack_require__.r(__webpack_exports__);
1576
1903
  if (self.isChildGrid) {
1577
1904
  pos.x -= self.canvasOffsetLeft;
1578
1905
  pos.y -= self.canvasOffsetTop;
1906
+ if (self.parentNode.rowGroupsAreaWidth) pos.x -= self.parentNode.rowGroupsAreaWidth;
1907
+ if (self.parentNode.columnGroupsAreaHeight) pos.y -= self.parentNode.columnGroupsAreaHeight;
1579
1908
  }
1580
1909
 
1581
1910
  return {
@@ -2344,6 +2673,40 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
2344
2673
 
2345
2674
  img.src = 'data:image/svg+xml;base64,' + btoa('<svg xmlns="http://www.w3.org/2000/svg" width="' + cell.width + '" height="' + cell.height + '">\n' + '<foreignObject class="node" x="0" y="0" width="100%" height="100%">\n' + '<body xmlns="http://www.w3.org/1999/xhtml" style="margin:0;padding:0;">\n' + v + '\n' + '</body>' + '</foreignObject>\n' + '</svg>\n');
2346
2675
  }
2676
+ /**
2677
+ * @param {number[]} coords [x0,y0, x1,y1, x2,y2, ...]
2678
+ */
2679
+
2680
+
2681
+ function strokeLines(coords) {
2682
+ if (coords.length < 4) return;
2683
+ self.ctx.beginPath();
2684
+ self.ctx.moveTo(coords[0] + self.canvasOffsetLeft, coords[1] + self.canvasOffsetTop);
2685
+
2686
+ for (var i = 2; i < coords.length; i += 2) {
2687
+ var x = coords[i] + self.canvasOffsetLeft;
2688
+ var y = coords[i + 1] + self.canvasOffsetTop;
2689
+ self.ctx.lineTo(x, y);
2690
+ }
2691
+
2692
+ self.ctx.stroke();
2693
+ }
2694
+ /**
2695
+ * @param {number} x based-X (left-top)
2696
+ * @param {number} y based-Y (left-top)
2697
+ * @param {number} width
2698
+ * @param {boolean} collapsed true: '+'; false: '-'
2699
+ */
2700
+
2701
+
2702
+ function drawGroupHandle(x, y, width, collapsed) {
2703
+ fillRect(x, y, width, width);
2704
+ strokeRect(x, y, width, width);
2705
+ var cx = x + width * 0.5;
2706
+ var cy = y + width * 0.5;
2707
+ strokeLines([x + width * 0.2, cy, x + width * 0.78, cy]);
2708
+ if (collapsed) strokeLines([cx, y + width * 0.22, cx, y + width * 0.8]);
2709
+ }
2347
2710
 
2348
2711
  function drawOrderByArrow(x, y) {
2349
2712
  var mt = self.style.columnHeaderOrderByArrowMarginTop * self.scale,
@@ -2407,6 +2770,52 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
2407
2770
  return ml + aw + mr;
2408
2771
  }
2409
2772
 
2773
+ function drawCellTreeIcon(cell, tree, rowTree) {
2774
+ var parentCount = rowTree ? tree.parentCount : 0;
2775
+ var iconSize = self.style.cellTreeIconWidth * self.scale,
2776
+ marginTop = self.style.cellTreeIconMarginTop * self.scale,
2777
+ marginRight = self.style.cellTreeIconMarginRight * self.scale,
2778
+ marginLeft = self.style.cellTreeIconMarginLeft * self.scale + parentCount * (iconSize + cell.paddingLeft);
2779
+ var x = cell.x + cell.paddingLeft + self.canvasOffsetLeft + marginLeft,
2780
+ y = cell.y + self.canvasOffsetTop + marginTop;
2781
+
2782
+ if (tree.icon) {
2783
+ self.ctx.beginPath();
2784
+ var oldFillStyle = self.ctx.fillStyle;
2785
+ var oldStrokeStyle = self.ctx.strokeStyle;
2786
+
2787
+ if (cell.hovered && self.hovers.onCellTreeIcon) {
2788
+ self.ctx.fillStyle = self.style.cellTreeIconHoverFillColor;
2789
+ } else {
2790
+ self.ctx.fillStyle = self.style.cellTreeIconFillColor;
2791
+ }
2792
+
2793
+ self.ctx.fillRect(x, y, iconSize, iconSize);
2794
+ self.ctx.strokeStyle = self.style.cellTreeIconBorderColor;
2795
+ self.ctx.rect(x, y, iconSize, iconSize);
2796
+ self.ctx.stroke();
2797
+ self.ctx.beginPath();
2798
+
2799
+ if (tree.expand) {
2800
+ self.ctx.moveTo(x + 3, y + iconSize * 0.5);
2801
+ self.ctx.lineTo(x + iconSize - 3, y + iconSize * 0.5);
2802
+ } else {
2803
+ self.ctx.moveTo(x + 2, y + iconSize * 0.5);
2804
+ self.ctx.lineTo(x + iconSize - 2, y + iconSize * 0.5);
2805
+ self.ctx.moveTo(x + iconSize * 0.5, y + 2);
2806
+ self.ctx.lineTo(x + iconSize * 0.5, y + iconSize - 2);
2807
+ }
2808
+
2809
+ self.ctx.lineWidth = self.style.cellTreeIconLineWidth;
2810
+ self.ctx.strokeStyle = self.style.cellTreeIconLineColor;
2811
+ self.ctx.stroke();
2812
+ self.ctx.strokeStyle = oldStrokeStyle;
2813
+ self.ctx.fillStyle = oldFillStyle;
2814
+ }
2815
+
2816
+ return marginLeft + iconSize + marginRight;
2817
+ }
2818
+
2410
2819
  function drawFilterButtonArrow(x, y) {
2411
2820
  var mt = (self.style.filterButtonHeight - self.style.filterButtonArrowHeight) / 2 * self.scale,
2412
2821
  ml = (self.style.filterButtonWidth - self.style.filterButtonArrowWidth) / 2 * self.scale,
@@ -2712,6 +3121,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
2712
3121
  }
2713
3122
 
2714
3123
  function drawText(cell) {
3124
+ var treeCellPadding = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
2715
3125
  var ll = cell.text.lines.length,
2716
3126
  h = cell.fontHeight * cell.lineHeight,
2717
3127
  x,
@@ -2722,12 +3132,12 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
2722
3132
  for (x = 0; x < cell.text.lines.length; x += 1) {
2723
3133
  line = cell.text.lines[x];
2724
3134
  var vPos = Math.max((cell.height - (wrap ? cell.text.height : cell.calculatedLineHeight)) * 0.5, 0) + h,
2725
- hPos = cell.paddingLeft + cell.treeArrowWidth + cell.orderByArrowWidth;
3135
+ hPos = cell.paddingLeft + treeCellPadding + cell.treeArrowWidth + cell.orderByArrowWidth;
2726
3136
 
2727
3137
  if (cell.horizontalAlignment === 'right') {
2728
- hPos = cell.paddingLeft + cell.paddedWidth - line.width;
3138
+ hPos = cell.paddingLeft + treeCellPadding + cell.paddedWidth - line.width;
2729
3139
  } else if (cell.horizontalAlignment === 'center') {
2730
- hPos = cell.paddingLeft + (cell.paddedWidth + cell.paddingRight) / 2 - line.width / 2;
3140
+ hPos = cell.paddingLeft + treeCellPadding + (cell.paddedWidth + cell.paddingRight) / 2 - line.width / 2;
2731
3141
  }
2732
3142
 
2733
3143
  if (cell.verticalAlignment === 'top') {
@@ -2773,6 +3183,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
2773
3183
  s = self.getSchema(),
2774
3184
  x = 0,
2775
3185
  n = Math.min(self.frozenColumn, s.length),
3186
+ collapsedGroups = self.getCollapsedColumnGroups(),
2776
3187
  column;
2777
3188
  hiddenFrozenColumnCount = 0;
2778
3189
 
@@ -2782,7 +3193,15 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
2782
3193
  if (column.hidden) {
2783
3194
  hiddenFrozenColumnCount += 1;
2784
3195
  } else {
2785
- w += self.getColumnWidth(x);
3196
+ var isCollapsed = collapsedGroups.findIndex(function (group) {
3197
+ return x >= group.from && x <= group.to;
3198
+ }) >= 0;
3199
+
3200
+ if (isCollapsed) {
3201
+ hiddenFrozenColumnCount += 1;
3202
+ } else {
3203
+ w += self.getColumnWidth(x);
3204
+ }
2786
3205
  }
2787
3206
 
2788
3207
  x += 1;
@@ -2860,6 +3279,19 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
2860
3279
  u = self.currentCell || {},
2861
3280
  columnHeaderCellHeight = self.getColumnHeaderCellHeight(),
2862
3281
  rowHeaderCellWidth = self.getRowHeaderCellWidth(),
3282
+ rowGroupsAreaWidth = self.getRowGroupAreaWidth(),
3283
+ columnGroupsAreaHeight = self.getColumnGroupAreaHeight(),
3284
+
3285
+ /** key: boundRowIndex, value: `{y,h}` */
3286
+ rowGroupsRectInfo = {},
3287
+
3288
+ /** value: `{y,h}` */
3289
+ rowGroupsFrozenInfo = {},
3290
+
3291
+ /** key: columnIndex, value: `{x,w}` */
3292
+ columnGroupsRectInfo = {},
3293
+ collapsedColumnGroups = self.getCollapsedColumnGroups(),
3294
+ collapsedRowGroups = self.getCollapsedRowGroups(),
2863
3295
  cellHeight = self.style.cellHeight;
2864
3296
  drawCount += 1;
2865
3297
  p = performance.now();
@@ -2869,6 +3301,36 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
2869
3301
  self.createRowOrders();
2870
3302
  }
2871
3303
 
3304
+ function saveRowGroupsRectInfo(cell) {
3305
+ var index = cell.boundRowIndex;
3306
+ if (index >= -1 === false) if (cell.rowIndex === -1) index = -1;else return;
3307
+ if (rowGroupsRectInfo[index]) return;
3308
+ rowGroupsRectInfo[index] = {
3309
+ y: cell.y,
3310
+ h: cell.height
3311
+ };
3312
+ }
3313
+
3314
+ function saveColumnGroupsRectInfo(cell) {
3315
+ var index = cell.columnIndex;
3316
+ if (columnGroupsRectInfo[index]) return;
3317
+ columnGroupsRectInfo[index] = {
3318
+ x: cell.x,
3319
+ w: cell.width
3320
+ };
3321
+ }
3322
+ /**
3323
+ * @param {number} columnIndex
3324
+ * @returns {boolean}
3325
+ */
3326
+
3327
+
3328
+ function isColumnCollapsedByGroup(columnIndex) {
3329
+ return collapsedColumnGroups.findIndex(function (group) {
3330
+ return columnIndex >= group.from && columnIndex <= group.to;
3331
+ }) >= 0;
3332
+ }
3333
+
2872
3334
  function drawScrollBars() {
2873
3335
  var drawCorner,
2874
3336
  en = self.scrollBox.entities,
@@ -3119,7 +3581,9 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3119
3581
  parentGrid: self.intf,
3120
3582
  innerHTML: '',
3121
3583
  activeHeader: activeHeader,
3122
- value: isHeader && !isRowHeader ? header.title || header.name : rawValue
3584
+ value: isHeader && !isRowHeader ? header.title || header.name : rawValue,
3585
+ isRowTree: rowOrderIndex >= 0 && columnOrderIndex == self.cellTree.rowTreeColIndex && self.cellTree.rows.length > 0 && self.cellTree.rows[rowOrderIndex].icon,
3586
+ isColumnTree: columnOrderIndex >= 0 && self.cellTree.columns[rowOrderIndex] && self.cellTree.columns[rowOrderIndex][columnOrderIndex].icon
3123
3587
  };
3124
3588
  cell.calculatedLineHeight = cell.fontHeight * cell.lineHeight + cell.lineSpacing;
3125
3589
  cell.paddedWidth = cell.width - cell.paddingRight - cell.paddingLeft;
@@ -3128,6 +3592,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3128
3592
  cell.userHeight = cell.isHeader ? self.sizes.rows[-1] : rowHeight;
3129
3593
  cell.userWidth = cell.isHeader ? self.sizes.columns.cornerCell : self.sizes.columns[headerIndex];
3130
3594
  self.visibleCells.unshift(cell);
3595
+ saveRowGroupsRectInfo(cell);
3596
+ saveColumnGroupsRectInfo(cell);
3131
3597
 
3132
3598
  if (self.dispatchEvent('beforerendercell', ev)) {
3133
3599
  return;
@@ -3270,7 +3736,27 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3270
3736
  if (cell.innerHTML || header.type === 'html') {
3271
3737
  drawHtml(cell);
3272
3738
  } else {
3273
- drawText(cell);
3739
+ var treeCellPadding = 0,
3740
+ isDrawText = true;
3741
+ if (cell.columnIndex == self.cellTree.rowTreeColIndex && !cell.isColumnHeader && self.cellTree.rows.length > 0 && Object.keys(self.cellTree.rows[cell.rowIndex]).length > 1) treeCellPadding = drawCellTreeIcon(cell, self.cellTree.rows[cell.rowIndex], true);
3742
+
3743
+ if (!cell.isRowHeader && cell.rowIndex > 0 && self.cellTree.columns[cell.rowIndex - 1] && self.cellTree.columns[cell.rowIndex - 1][cell.columnIndex].icon) {
3744
+ for (var r = cell.rowIndex - 1; r >= 0; r--) {
3745
+ if (!self.cellTree.columns[r]) break;
3746
+ if (!self.cellTree.columns[r][cell.columnIndex].icon) break;
3747
+
3748
+ if (!self.cellTree.columns[r][cell.columnIndex].expand) {
3749
+ isDrawText = false;
3750
+ break;
3751
+ }
3752
+ }
3753
+ }
3754
+
3755
+ if (isDrawText && !cell.isRowHeader && self.cellTree.columns[cell.rowIndex] && self.cellTree.columns[cell.rowIndex][cell.columnIndex].icon) {
3756
+ if (self.viewData.length > 0 && self.viewData[cell.rowIndex][cell.columnIndex].length > 0) treeCellPadding = drawCellTreeIcon(cell, self.cellTree.columns[cell.rowIndex][cell.columnIndex], false);
3757
+ }
3758
+
3759
+ if (isDrawText) drawText(cell, treeCellPadding);
3274
3760
  }
3275
3761
 
3276
3762
  if (wrap && cell.text && cell.text.height > rowHeight) {
@@ -3310,6 +3796,12 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3310
3796
  var previousRowNumber = self.getBoundRowIndexFromViewRowIndex(rowOrderIndex - 1);
3311
3797
  var hasRowGap = previousRowNumber !== undefined && cell.boundRowIndex > 0 && cell.boundRowIndex - previousRowNumber > 1;
3312
3798
 
3799
+ if (hasRowGap && collapsedRowGroups.length > 0) {
3800
+ hasRowGap = collapsedRowGroups.find(function (group) {
3801
+ return group.from === previousRowNumber && group.to === cell.boundRowIndex;
3802
+ }) >= 0;
3803
+ }
3804
+
3313
3805
  if (hasRowGap) {
3314
3806
  var barHeight = self.style.rowHeaderCellRowNumberGapHeight;
3315
3807
  var barColor = self.style.rowHeaderCellRowNumberGapColor;
@@ -3360,7 +3852,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3360
3852
  // added to the end, and we want to render that new row's number
3361
3853
 
3362
3854
  var filteredRowNumber = self.viewData && rowIndex < self.viewData.length ? self.getBoundRowIndexFromViewRowIndex(rowIndex) + 1 : self.originalData ? self.originalData.length + 1 : rowOrderIndex + 1;
3363
- var rowHeaderValue = self.hasActiveFilters() ? filteredRowNumber : rowIndex + 1;
3855
+ var rowHeaderValue = self.hasActiveFilters() || self.hasCollapsedRowGroup() ? filteredRowNumber : rowIndex + 1;
3364
3856
  var _rowHeaderCell = {
3365
3857
  rowHeaderCell: rowHeaderValue
3366
3858
  };
@@ -3393,7 +3885,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3393
3885
  i = self.orders.columns[o];
3394
3886
  header = schema[i];
3395
3887
 
3396
- if (!header.hidden) {
3888
+ if (!header.hidden && !isColumnCollapsedByGroup(o)) {
3397
3889
  d = {
3398
3890
  title: header.title,
3399
3891
  name: header.name,
@@ -3512,8 +4004,10 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3512
4004
  cellHeight = rowHeight; //draw normal columns
3513
4005
 
3514
4006
  for (columnOrderIndex = self.scrollIndexLeft; columnOrderIndex < g; columnOrderIndex += 1) {
3515
- headerIndex = self.orders.columns[columnOrderIndex];
3516
- x += drawCell(rowData, rowOrderIndex, rowIndex)(schema[headerIndex], headerIndex, columnOrderIndex);
4007
+ if (!isColumnCollapsedByGroup(columnOrderIndex)) {
4008
+ headerIndex = self.orders.columns[columnOrderIndex];
4009
+ x += drawCell(rowData, rowOrderIndex, rowIndex)(schema[headerIndex], headerIndex, columnOrderIndex);
4010
+ }
3517
4011
 
3518
4012
  if (x > self.width) {
3519
4013
  self.scrollIndexRight = columnOrderIndex;
@@ -3530,8 +4024,10 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3530
4024
  }
3531
4025
 
3532
4026
  for (columnOrderIndex = 0; columnOrderIndex < self.frozenColumn; columnOrderIndex += 1) {
3533
- headerIndex = self.orders.columns[columnOrderIndex];
3534
- x += drawCell(rowData, rowOrderIndex, rowIndex)(schema[headerIndex], headerIndex, columnOrderIndex);
4027
+ if (!isColumnCollapsedByGroup(columnOrderIndex)) {
4028
+ headerIndex = self.orders.columns[columnOrderIndex];
4029
+ x += drawCell(rowData, rowOrderIndex, rowIndex)(schema[headerIndex], headerIndex, columnOrderIndex);
4030
+ }
3535
4031
 
3536
4032
  if (x > self.width) {
3537
4033
  break;
@@ -3558,8 +4054,19 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3558
4054
  nodeType: 'canvas-datagrid-tree',
3559
4055
  scrollTop: self.scrollBox.scrollTop,
3560
4056
  scrollLeft: self.scrollBox.scrollLeft,
3561
- rowIndex: rowOrderIndex
4057
+ rowIndex: rowOrderIndex,
4058
+ columnGroupsAreaHeight: columnGroupsAreaHeight,
4059
+ rowGroupsAreaWidth: rowGroupsAreaWidth
3562
4060
  };
4061
+
4062
+ if (self.intf.parentNode) {
4063
+ var _self$intf$parentNode = self.intf.parentNode,
4064
+ _columnGroupsAreaHeight = _self$intf$parentNode.columnGroupsAreaHeight,
4065
+ _rowGroupsAreaWidth = _self$intf$parentNode.rowGroupsAreaWidth;
4066
+ treeGrid.parentNode.columnGroupsAreaHeight += _columnGroupsAreaHeight || 0;
4067
+ treeGrid.parentNode.rowGroupsAreaWidth += _rowGroupsAreaWidth || 0;
4068
+ }
4069
+
3563
4070
  self.visibleCells.unshift({
3564
4071
  rowIndex: rowOrderIndex,
3565
4072
  columnIndex: 0,
@@ -3586,6 +4093,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3586
4093
  self.visibleRows = [];
3587
4094
  schema = self.getSchema();
3588
4095
  self.visibleCells = [];
4096
+ self.visibleGroups = [];
3589
4097
  self.canvasOffsetTop = self.isChildGrid ? self.parentNode.offsetTop : 0.5;
3590
4098
  self.canvasOffsetLeft = self.isChildGrid ? self.parentNode.offsetLeft : -0.5;
3591
4099
  h = self.height;
@@ -3599,87 +4107,511 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3599
4107
  fillRect(0, 0, w, h);
3600
4108
  }
3601
4109
 
3602
- function drawFrozenRows() {
3603
- var rowOrderIndex,
3604
- ln = Math.min(viewData.length, self.frozenRow);
3605
- x = -self.scrollBox.scrollLeft + self.scrollPixelLeft + self.style.cellBorderWidth;
3606
- y = columnHeaderCellHeight;
4110
+ function initGroupArea() {
4111
+ self.ctx.translate(rowGroupsAreaWidth, columnGroupsAreaHeight);
4112
+ }
3607
4113
 
3608
- for (rowIndex = 0; rowIndex < ln; rowIndex += 1) {
3609
- rowOrderIndex = self.orders.rows[rowIndex];
4114
+ function drawGroupArea() {
4115
+ var mx = rowGroupsAreaWidth;
4116
+ var my = columnGroupsAreaHeight;
4117
+ var frozenColumnsWidth = getFrozenColumnsWidth();
4118
+ var frozenRowsHeight = rowGroupsFrozenInfo.y + rowGroupsFrozenInfo.h - columnHeaderCellHeight;
4119
+ var onTheLeft = self.attributes.columnGroupIndicatorPosition === 'left';
4120
+ var onTheTop = self.attributes.rowGroupIndicatorPosition === 'top';
4121
+ /** @type {CanvasRenderingContext2D} */
3610
4122
 
3611
- if (!drawRow(rowOrderIndex, rowIndex)) {
3612
- break;
3613
- }
3614
- }
4123
+ var ctx = self.ctx;
4124
+ ctx.save();
4125
+ ctx.fillStyle = self.style.groupingAreaBackgroundColor;
4126
+ fillRect(0, -my, w, my);
4127
+ fillRect(-mx, -my, mx, h);
4128
+ ctx.restore(); //#region Columns Grouping
3615
4129
 
3616
- if (self.attributes.allowFreezingRows) {
3617
- // HACK great, another stupid magic number.
3618
- // Background will appear as a 0.5px artifact behind the row freeze bar without this hack
3619
- y += self.style.frozenMarkerBorderWidth + self.style.frozenMarkerWidth - 0.4999999999;
3620
- }
4130
+ /** it extends `self.groupedRows` */
3621
4131
 
3622
- self.lastFrozenRowPixel = y;
3623
- }
4132
+ var groupedColumns = [];
3624
4133
 
3625
- function drawRows() {
3626
- self.ctx.save();
4134
+ for (var row = 0; row < self.groupedColumns.length; row++) {
4135
+ var groups = self.groupedColumns[row];
3627
4136
 
3628
- if (self.frozenRow > 0) {
3629
- radiusRect(0, self.lastFrozenRowPixel, self.width, self.height - self.lastFrozenRowPixel, 0);
3630
- self.ctx.clip();
4137
+ for (var j = 0; j < groups.length; j++) {
4138
+ groupedColumns.push(Object.assign({
4139
+ row: row
4140
+ }, groups[j]));
4141
+ }
3631
4142
  }
3632
4143
 
3633
- var columnOrderIndex,
3634
- rowOrderIndex,
3635
- headerIndex,
3636
- g = schema.length;
3637
- x = -self.scrollBox.scrollLeft + self.scrollPixelLeft + self.style.cellBorderWidth;
4144
+ if (groupedColumns.length > 0) {
4145
+ (function () {
4146
+ var rowHeight = self.style.columnGroupRowHeight;
4147
+ var toggleHandleSize = rowHeight * 0.5;
4148
+ var toggleHandlePadding = (rowHeight - toggleHandleSize) * 0.5;
3638
4149
 
3639
- if (!self.attributes.snapToRow) {
3640
- y += -self.scrollBox.scrollTop + self.scrollPixelTop + self.style.cellBorderWidth;
3641
- }
4150
+ var _loop = function _loop(i) {
4151
+ var group = groupedColumns[i];
4152
+ var row = group.row,
4153
+ collapsed = group.collapsed;
4154
+ var topY = -my + row * rowHeight;
4155
+ var centerY = topY + rowHeight * 0.5;
4156
+ var bottomY = topY + rowHeight - toggleHandlePadding;
4157
+ var leftmostX = rowHeaderCellWidth - toggleHandleSize - toggleHandlePadding;
3642
4158
 
3643
- for (rowIndex = self.frozenRow + self.scrollIndexTop; rowIndex < l; rowIndex += 1) {
3644
- rowOrderIndex = self.orders.rows[rowIndex];
3645
- self.scrollIndexBottom = rowIndex;
3646
- self.scrollPixelBottom = y;
4159
+ var drawGroupHandleAtX = function drawGroupHandleAtX(x) {
4160
+ return drawGroupHandle(x, topY + toggleHandlePadding, toggleHandleSize, group.collapsed);
4161
+ };
3647
4162
 
3648
- if (!drawRow(rowOrderIndex, rowIndex)) {
3649
- break;
3650
- }
3651
- }
4163
+ var pushToVisibleGroups = function pushToVisibleGroups(leftX, rightX) {
4164
+ return self.visibleGroups.push({
4165
+ type: 'c',
4166
+ collapsed: collapsed,
4167
+ from: group.from,
4168
+ to: group.to,
4169
+ row: row,
4170
+ x: leftX + mx,
4171
+ y: topY + my,
4172
+ x2: rightX + mx,
4173
+ y2: bottomY + my
4174
+ });
4175
+ }; //#region check the relationship between this group and frozen columns
3652
4176
 
3653
- if (self.attributes.showNewRow) {
3654
- if (self.attributes.showRowHeaders) {
3655
- x += rowHeaderCellWidth;
3656
- }
3657
4177
 
3658
- rowHeight = cellHeight = self.style.cellHeight;
3659
- rowOpen = false;
4178
+ var crossTheFrozen = group.from < self.frozenColumn && group.to >= self.frozenColumn;
4179
+ var notInFrozen = group.from >= self.frozenColumn; //#endregion
3660
4180
 
3661
- for (columnOrderIndex = self.scrollIndexLeft; columnOrderIndex < g; columnOrderIndex += 1) {
3662
- headerIndex = self.orders.columns[columnOrderIndex];
3663
- x += drawCell(self.newRow, viewData.length, viewData.length)(schema[headerIndex], headerIndex, columnOrderIndex);
4181
+ if (collapsed) {
4182
+ var _leftX = leftmostX + toggleHandleSize; // This group is not sticking on the first column
3664
4183
 
3665
- if (x > self.width + self.scrollBox.scrollLeft) {
3666
- break;
3667
- }
3668
- }
3669
4184
 
3670
- rowHeaders.push([self.newRow, viewData.length, viewData.length, y, rowHeight]);
3671
- }
4185
+ if (group.from > 0) {
4186
+ var colIndex = group.to + 1;
4187
+ var col = columnGroupsRectInfo[colIndex];
3672
4188
 
3673
- self.ctx.restore();
3674
- }
4189
+ if (!col) {
4190
+ colIndex = group.from - 1;
4191
+ col = columnGroupsRectInfo[colIndex];
4192
+ if (!col) return "continue"; // don't draw this group indicator because it is invisible
3675
4193
 
3676
- function drawMoveMarkers() {
3677
- if (!self.movingSelection) {
3678
- return;
3679
- }
4194
+ _leftX = col.x + col.w - toggleHandleSize * 0.5;
4195
+ } else {
4196
+ _leftX = col.x + toggleHandlePadding;
4197
+ }
3680
4198
 
3681
- self.ctx.lineWidth = self.style.moveOverlayBorderWidth;
3682
- self.ctx.strokeStyle = self.style.moveOverlayBorderColor;
4199
+ if (colIndex >= self.frozenColumn) {
4200
+ var compare = frozenColumnsWidth + rowHeaderCellWidth - toggleHandlePadding; // don't draw this group indicator because it is hidden by frozen columns
4201
+
4202
+ if (_leftX < compare) return "continue";
4203
+ }
4204
+ }
4205
+
4206
+ var _rightX = _leftX + toggleHandleSize;
4207
+
4208
+ ctx.save();
4209
+ ctx.strokeStyle = self.style.groupIndicatorColor;
4210
+ ctx.fillStyle = self.style.groupIndicatorBackgroundColor;
4211
+ drawGroupHandleAtX(_leftX);
4212
+ ctx.restore();
4213
+ pushToVisibleGroups(_leftX, _rightX);
4214
+ } // end of collapsed group
4215
+
4216
+ /** @type {number} pointer for loop */
4217
+
4218
+
4219
+ var ptr = void 0;
4220
+ var left = columnGroupsRectInfo[group.from];
4221
+ var right = columnGroupsRectInfo[group.to];
4222
+ var containsBegining = true;
4223
+ var containsEnd = true;
4224
+ ptr = group.from;
4225
+
4226
+ while (!left && ptr < group.to) {
4227
+ left = columnGroupsRectInfo[++ptr];
4228
+ containsBegining = false;
4229
+ }
4230
+
4231
+ ptr = group.to;
4232
+
4233
+ while (!right && ptr > group.from) {
4234
+ right = columnGroupsRectInfo[--ptr];
4235
+ containsEnd = false;
4236
+ }
4237
+
4238
+ if (!left || !right) return "continue";
4239
+ var rightX = right.x + right.w;
4240
+ var leftX = left.x;
4241
+
4242
+ if (crossTheFrozen) {
4243
+ var rightCompare = columnGroupsRectInfo[self.frozenColumn - 1];
4244
+
4245
+ if (rightCompare) {
4246
+ var compareX = rightCompare.x + rightCompare.w;
4247
+ if (!onTheLeft) compareX += toggleHandleSize;
4248
+
4249
+ if (compareX >= rightX) {
4250
+ right = rightCompare;
4251
+ rightX = right.x + right.w;
4252
+ containsEnd = false;
4253
+ }
4254
+ }
4255
+ }
4256
+
4257
+ var minLeftX = rowHeaderCellWidth + (notInFrozen ? frozenColumnsWidth : 0);
4258
+ if (rightX + (onTheLeft ? 0 : toggleHandleSize) < minLeftX) return "continue";
4259
+ rightX -= toggleHandlePadding;
4260
+ leftX += toggleHandlePadding;
4261
+ ctx.save();
4262
+ ctx.strokeStyle = self.style.groupIndicatorColor;
4263
+ ctx.fillStyle = self.style.groupIndicatorBackgroundColor;
4264
+ var lineCoords = [];
4265
+
4266
+ if (onTheLeft) {
4267
+ // avoid lines from two groups be overlapping
4268
+ minLeftX += toggleHandlePadding * 2;
4269
+ if (leftX < minLeftX) leftX = minLeftX;
4270
+ if (group.from === 0) leftX -= toggleHandlePadding * 2;
4271
+
4272
+ if (rightX >= leftX) {
4273
+ lineCoords.push(leftX, centerY, rightX, centerY);
4274
+ if (containsEnd) lineCoords.push(rightX, bottomY);
4275
+ } else {
4276
+ rightX = leftX;
4277
+ }
4278
+
4279
+ leftX -= toggleHandleSize;
4280
+ drawGroupHandleAtX(leftX); // add more clickable area into `visibleGroups`
4281
+
4282
+ rightX += toggleHandlePadding - 1;
4283
+ } else {
4284
+ // handle on the right
4285
+ if (leftX < minLeftX) leftX = minLeftX;
4286
+ if (group.from === 0) leftX -= toggleHandlePadding * 2;
4287
+
4288
+ if (containsEnd) {
4289
+ if (group.to === self.frozenColumn - 1) {
4290
+ rightX -= toggleHandleSize;
4291
+ } else {
4292
+ rightX += toggleHandlePadding * 2;
4293
+ }
4294
+
4295
+ drawGroupHandleAtX(rightX);
4296
+ }
4297
+
4298
+ if (leftX > rightX) {
4299
+ leftX = rightX;
4300
+ } else {
4301
+ if (group.from === 0) {
4302
+ containsBegining = true;
4303
+ leftX = leftmostX + toggleHandleSize;
4304
+ }
4305
+
4306
+ if (containsBegining) lineCoords.push(leftX, bottomY);
4307
+ lineCoords.push(leftX, centerY, rightX, centerY);
4308
+ } // add more clickable area into `visibleGroups`
4309
+
4310
+
4311
+ leftX -= toggleHandlePadding + 1;
4312
+ if (containsEnd) rightX += toggleHandleSize;
4313
+ }
4314
+
4315
+ strokeLines(lineCoords);
4316
+ ctx.restore();
4317
+ pushToVisibleGroups(leftX, rightX);
4318
+ };
4319
+
4320
+ for (var i = 0; i < groupedColumns.length; i++) {
4321
+ var _ret = _loop(i);
4322
+
4323
+ if (_ret === "continue") continue;
4324
+ }
4325
+ })();
4326
+ } //#endregion Columns Grouping
4327
+ //#region Rows Grouping
4328
+
4329
+ /** it extends `self.groupedRows` */
4330
+
4331
+
4332
+ var groupedRows = [];
4333
+
4334
+ for (var col = 0; col < self.groupedRows.length; col++) {
4335
+ var _groups = self.groupedRows[col];
4336
+
4337
+ for (var _j = 0; _j < _groups.length; _j++) {
4338
+ groupedRows.push(Object.assign({
4339
+ col: col
4340
+ }, _groups[_j]));
4341
+ }
4342
+ }
4343
+
4344
+ if (groupedRows.length > 0) {
4345
+ (function () {
4346
+ var colWidth = self.style.rowGroupColumnWidth;
4347
+ var toggleHandleSize = colWidth * 0.5;
4348
+ var toggleHandlePadding = (colWidth - toggleHandleSize) * 0.5;
4349
+
4350
+ var _loop2 = function _loop2(i) {
4351
+ var group = groupedRows[i];
4352
+ var col = group.col,
4353
+ collapsed = group.collapsed;
4354
+ var leftX = -mx + col * colWidth;
4355
+ var centerX = leftX + colWidth * 0.5;
4356
+ var rightX = leftX + colWidth - toggleHandlePadding;
4357
+ var topmostY = columnHeaderCellHeight - toggleHandleSize - toggleHandlePadding;
4358
+
4359
+ var drawGroupHandleAtY = function drawGroupHandleAtY(y) {
4360
+ return drawGroupHandle(leftX + toggleHandlePadding, y, toggleHandleSize, group.collapsed);
4361
+ };
4362
+
4363
+ var pushToVisibleGroups = function pushToVisibleGroups(topY, bottomY) {
4364
+ return self.visibleGroups.push({
4365
+ type: 'r',
4366
+ collapsed: collapsed,
4367
+ from: group.from,
4368
+ to: group.to,
4369
+ col: col,
4370
+ x: leftX + mx,
4371
+ y: topY + my,
4372
+ x2: rightX + mx,
4373
+ y2: bottomY + my
4374
+ });
4375
+ }; //#region check the relationship between this group and frozen columns
4376
+
4377
+
4378
+ var crossTheFrozen = group.from < self.frozenRow && group.to >= self.frozenRow;
4379
+ var notInFrozen = group.from >= self.frozenRow; //#endregion
4380
+
4381
+ if (collapsed) {
4382
+ var _topY = topmostY + toggleHandleSize; // This group is not sticking on the first column
4383
+
4384
+
4385
+ if (group.from > 0) {
4386
+ var _rowIndex = group.to + 1;
4387
+
4388
+ var _row = rowGroupsRectInfo[_rowIndex];
4389
+
4390
+ if (!_row) {
4391
+ _rowIndex = group.from - 1;
4392
+ _row = rowGroupsRectInfo[_rowIndex];
4393
+ if (!_row) return "continue"; // don't draw this group indicator because it is invisible
4394
+
4395
+ _topY = _row.y + _row.h - toggleHandleSize * 0.5;
4396
+ } else {
4397
+ _topY = _row.y;
4398
+ }
4399
+
4400
+ if (_rowIndex >= self.frozenRow) {
4401
+ var compare = frozenRowsHeight + columnHeaderCellHeight - toggleHandlePadding; // don't draw this group indicator because it is hidden by frozen columns
4402
+
4403
+ if (_topY < compare) return "continue";
4404
+ }
4405
+ }
4406
+
4407
+ var _bottomY = _topY + toggleHandleSize;
4408
+
4409
+ ctx.save();
4410
+ ctx.strokeStyle = self.style.groupIndicatorColor;
4411
+ ctx.fillStyle = self.style.groupIndicatorBackgroundColor;
4412
+ drawGroupHandleAtY(_topY);
4413
+ ctx.restore();
4414
+ pushToVisibleGroups(_topY, _bottomY);
4415
+ } // end of collapsed group
4416
+
4417
+ /** @type {number} pointer for loop */
4418
+
4419
+
4420
+ var ptr = void 0;
4421
+ var top = rowGroupsRectInfo[group.from];
4422
+ var bottom = rowGroupsRectInfo[group.to];
4423
+ var containsBegining = true;
4424
+ var containsEnd = true;
4425
+ ptr = group.from;
4426
+
4427
+ while (!top && ptr < group.to) {
4428
+ top = rowGroupsRectInfo[++ptr];
4429
+ containsBegining = false;
4430
+ }
4431
+
4432
+ ptr = group.to;
4433
+
4434
+ while (!bottom && ptr > group.from) {
4435
+ bottom = rowGroupsRectInfo[--ptr];
4436
+ containsEnd = false;
4437
+ }
4438
+
4439
+ if (!top || !bottom) return "continue";
4440
+ var bottomY = bottom.y + bottom.h;
4441
+ var topY = top.y;
4442
+
4443
+ if (crossTheFrozen) {
4444
+ var bottomCompare = rowGroupsRectInfo[self.frozenRow - 1];
4445
+
4446
+ if (bottomCompare) {
4447
+ var compareY = bottomCompare.y + bottomCompare.h;
4448
+ if (!onTheTop) compareY += toggleHandleSize;
4449
+
4450
+ if (compareY >= bottomY) {
4451
+ bottom = bottomCompare;
4452
+ bottomY = bottom.y + bottom.h;
4453
+ containsEnd = false;
4454
+ }
4455
+ }
4456
+ }
4457
+
4458
+ var minTopY = columnHeaderCellHeight + (notInFrozen ? frozenRowsHeight : 0);
4459
+ if (bottomY + (onTheTop ? 0 : toggleHandleSize) < minTopY) return "continue";
4460
+ bottomY -= toggleHandlePadding;
4461
+ topY += toggleHandlePadding;
4462
+ ctx.save();
4463
+ ctx.strokeStyle = self.style.groupIndicatorColor;
4464
+ ctx.fillStyle = self.style.groupIndicatorBackgroundColor;
4465
+ var lineCoords = [];
4466
+
4467
+ if (onTheTop) {
4468
+ // avoid lines from two groups be overlapping
4469
+ minTopY += toggleHandlePadding * 2;
4470
+ if (topY < minTopY) topY = minTopY;
4471
+ if (group.from === 0) topY -= toggleHandlePadding * 2;
4472
+
4473
+ if (bottomY >= topY) {
4474
+ lineCoords.push(centerX, topY, centerX, bottomY);
4475
+ if (containsEnd) lineCoords.push(rightX, bottomY);
4476
+ } else {
4477
+ bottomY = topY;
4478
+ }
4479
+
4480
+ topY -= toggleHandleSize;
4481
+ drawGroupHandleAtY(topY); // add more clickable area into `visibleGroups`
4482
+
4483
+ bottomY += toggleHandlePadding - 1;
4484
+ } else {
4485
+ // handle on the bottom
4486
+ if (topY < minTopY) topY = minTopY;
4487
+ if (group.from === 0) topY -= toggleHandlePadding * 2;
4488
+
4489
+ if (containsEnd) {
4490
+ if (group.to === self.frozenRow - 1) {
4491
+ bottomY -= toggleHandleSize;
4492
+ } else {// bottomY += toggleHandlePadding * 2;
4493
+ }
4494
+
4495
+ drawGroupHandleAtY(bottomY);
4496
+ }
4497
+
4498
+ if (topY > bottomY) {
4499
+ topY = bottomY;
4500
+ } else {
4501
+ if (group.from === 0) {
4502
+ containsBegining = true;
4503
+ topY = topmostY + toggleHandleSize;
4504
+ }
4505
+
4506
+ if (containsBegining) lineCoords.push(rightX, topY);
4507
+ lineCoords.push(centerX, topY, centerX, bottomY); // add more clickable area into `visibleGroups`
4508
+
4509
+ topY -= toggleHandlePadding + 1;
4510
+ } // add more clickable area into `visibleGroups`
4511
+
4512
+
4513
+ if (containsEnd) bottomY += toggleHandleSize;
4514
+ }
4515
+
4516
+ strokeLines(lineCoords);
4517
+ ctx.restore();
4518
+ pushToVisibleGroups(topY, bottomY);
4519
+ };
4520
+
4521
+ for (var i = 0; i < groupedRows.length; i++) {
4522
+ var _ret2 = _loop2(i);
4523
+
4524
+ if (_ret2 === "continue") continue;
4525
+ }
4526
+ })();
4527
+ } //#endregion Rows Grouping
4528
+
4529
+ }
4530
+
4531
+ function drawFrozenRows() {
4532
+ var rowOrderIndex,
4533
+ ln = Math.min(viewData.length, self.frozenRow);
4534
+ x = -self.scrollBox.scrollLeft + self.scrollPixelLeft + self.style.cellBorderWidth;
4535
+ y = columnHeaderCellHeight;
4536
+
4537
+ for (rowIndex = 0; rowIndex < ln; rowIndex += 1) {
4538
+ rowOrderIndex = self.orders.rows[rowIndex];
4539
+
4540
+ if (!drawRow(rowOrderIndex, rowIndex)) {
4541
+ break;
4542
+ }
4543
+ }
4544
+
4545
+ if (self.attributes.allowFreezingRows) {
4546
+ // HACK great, another stupid magic number.
4547
+ // Background will appear as a 0.5px artifact behind the row freeze bar without this hack
4548
+ y += self.style.frozenMarkerBorderWidth + self.style.frozenMarkerWidth - 0.4999999999;
4549
+ }
4550
+
4551
+ self.lastFrozenRowPixel = y;
4552
+ }
4553
+
4554
+ function drawRows() {
4555
+ self.ctx.save();
4556
+
4557
+ if (self.frozenRow > 0) {
4558
+ radiusRect(0, self.lastFrozenRowPixel, self.width, self.height - self.lastFrozenRowPixel, 0);
4559
+ self.ctx.clip();
4560
+ }
4561
+
4562
+ var columnOrderIndex,
4563
+ rowOrderIndex,
4564
+ headerIndex,
4565
+ g = schema.length;
4566
+ x = -self.scrollBox.scrollLeft + self.scrollPixelLeft + self.style.cellBorderWidth;
4567
+
4568
+ if (!self.attributes.snapToRow) {
4569
+ y += -self.scrollBox.scrollTop + self.scrollPixelTop + self.style.cellBorderWidth;
4570
+ }
4571
+
4572
+ for (rowIndex = self.frozenRow + self.scrollIndexTop; rowIndex < l; rowIndex += 1) {
4573
+ rowOrderIndex = self.orders.rows[rowIndex];
4574
+ self.scrollIndexBottom = rowIndex;
4575
+ self.scrollPixelBottom = y;
4576
+ if (self.cellTree.rows.length > 0 && Object.keys(self.cellTree.rows[rowOrderIndex]).length > 0 && self.cellTree.rows[rowOrderIndex].hide) continue;
4577
+
4578
+ if (!drawRow(rowOrderIndex, rowIndex)) {
4579
+ break;
4580
+ }
4581
+ }
4582
+
4583
+ if (self.attributes.showNewRow) {
4584
+ if (self.attributes.showRowHeaders) {
4585
+ x += rowHeaderCellWidth;
4586
+ }
4587
+
4588
+ rowHeight = cellHeight = self.style.cellHeight;
4589
+ rowOpen = false;
4590
+
4591
+ for (columnOrderIndex = self.scrollIndexLeft; columnOrderIndex < g; columnOrderIndex += 1) {
4592
+ if (!isColumnCollapsedByGroup(columnOrderIndex)) {
4593
+ headerIndex = self.orders.columns[columnOrderIndex];
4594
+ x += drawCell(self.newRow, viewData.length, viewData.length)(schema[headerIndex], headerIndex, columnOrderIndex);
4595
+ }
4596
+
4597
+ if (x > self.width + self.scrollBox.scrollLeft) {
4598
+ break;
4599
+ }
4600
+ }
4601
+
4602
+ rowHeaders.push([self.newRow, viewData.length, viewData.length, y, rowHeight]);
4603
+ }
4604
+
4605
+ self.ctx.restore();
4606
+ }
4607
+
4608
+ function drawMoveMarkers() {
4609
+ if (!self.movingSelection) {
4610
+ return;
4611
+ }
4612
+
4613
+ self.ctx.lineWidth = self.style.moveOverlayBorderWidth;
4614
+ self.ctx.strokeStyle = self.style.moveOverlayBorderColor;
3683
4615
  self.ctx.setLineDash(self.style.moveOverlayBorderSegments);
3684
4616
  moveBorders.forEach(function (c) {
3685
4617
  addBorderLine(c[0], c[1]);
@@ -3839,6 +4771,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3839
4771
  }
3840
4772
 
3841
4773
  function drawFrozenMarkers() {
4774
+ if (self.dragStartObject !== undefined) return;
3842
4775
  var my = self.lastFrozenRowPixel - self.style.frozenMarkerWidth,
3843
4776
  mx = self.lastFrozenColumnPixel - self.style.frozenMarkerBorderWidth,
3844
4777
  xHover = self.currentCell && self.currentCell.style === 'frozen-row-marker',
@@ -3864,13 +4797,18 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3864
4797
  self.ctx.strokeStyle = xHover ? self.style.frozenMarkerHoverBorderColor : self.style.frozenMarkerBorderColor;
3865
4798
  fillRect(0, my, self.width, self.style.frozenMarkerWidth);
3866
4799
  strokeRect(0, my, self.width, self.style.frozenMarkerWidth);
4800
+ var height = self.style.frozenMarkerWidth + self.style.frozenMarkerBorderWidth;
3867
4801
  self.visibleCells.unshift({
3868
4802
  x: 0,
3869
4803
  y: my,
3870
- height: self.style.frozenMarkerWidth + self.style.frozenMarkerBorderWidth,
4804
+ height: height,
3871
4805
  width: self.width,
3872
4806
  style: 'frozen-row-marker'
3873
4807
  });
4808
+ rowGroupsFrozenInfo = {
4809
+ y: my,
4810
+ h: height
4811
+ };
3874
4812
  }
3875
4813
 
3876
4814
  if (self.freezeMarkerPosition) {
@@ -4032,6 +4970,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4032
4970
  self.ctx.save();
4033
4971
  initDraw();
4034
4972
  drawBackground();
4973
+ initGroupArea();
4035
4974
  drawFrozenRows();
4036
4975
  drawRows();
4037
4976
  drawActiveCell();
@@ -4048,6 +4987,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4048
4987
  self.resize(true);
4049
4988
  }
4050
4989
 
4990
+ drawGroupArea();
4051
4991
  drawDebug();
4052
4992
  drawPerfLines();
4053
4993
 
@@ -4221,6 +5161,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4221
5161
  l = (self.viewData || []).length,
4222
5162
  columnHeaderCellHeight = self.getColumnHeaderCellHeight(),
4223
5163
  rowHeaderCellWidth = self.getRowHeaderCellWidth(),
5164
+ topGroupAreaHeight = self.getColumnGroupAreaHeight(),
5165
+ leftGroupAreaWidth = self.getRowGroupAreaWidth(),
4224
5166
  ch = self.style.cellHeight,
4225
5167
  s = self.getSchema(); // sets actual DOM canvas element
4226
5168
 
@@ -4232,8 +5174,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4232
5174
  }
4233
5175
 
4234
5176
  function setScrollBoxSize() {
4235
- self.scrollBox.width = self.width - rowHeaderCellWidth;
4236
- self.scrollBox.height = self.height - columnHeaderCellHeight;
5177
+ self.scrollBox.width = self.width - rowHeaderCellWidth - leftGroupAreaWidth;
5178
+ self.scrollBox.height = self.height - columnHeaderCellHeight - topGroupAreaHeight;
4237
5179
  }
4238
5180
 
4239
5181
  function setCanvasSize() {
@@ -4243,8 +5185,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4243
5185
 
4244
5186
  dims = {
4245
5187
  // HACK +1 ? maybe it's a magic cell border? Required to line up properly in auto height mode.
4246
- height: columnHeaderCellHeight + dataHeight + cellBorder + 1,
4247
- width: dataWidth + rowHeaderCellWidth + cellBorder
5188
+ height: columnHeaderCellHeight + topGroupAreaHeight + dataHeight + cellBorder + 1,
5189
+ width: dataWidth + rowHeaderCellWidth + cellBorder + leftGroupAreaWidth
4248
5190
  };
4249
5191
  ['width', 'height'].forEach(function (dim) {
4250
5192
  //TODO: support inherit
@@ -4273,18 +5215,32 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4273
5215
  self.scrollCache.y[x] = dataHeight;
4274
5216
  }
4275
5217
 
5218
+ var collapsedColumnGroups = self.getCollapsedColumnGroups();
5219
+
5220
+ var isColumnCollapsed = function isColumnCollapsed(columnIndex) {
5221
+ return collapsedColumnGroups.findIndex(function (group) {
5222
+ return columnIndex >= group.from && columnIndex <= group.to;
5223
+ }) >= 0;
5224
+ };
5225
+ /** @type {number} it will be used in `reduceSchema` only */
5226
+
5227
+
5228
+ var frozenWidth = 0;
4276
5229
  dataWidth = s.reduce(function reduceSchema(accumulator, column, columnIndex) {
4277
5230
  // intentional redefintion of column. This causes scrollCache to be in the correct order
4278
- column = s[self.orders.columns[columnIndex]];
5231
+ var schemaIndex = self.orders.columns[columnIndex];
5232
+ var columnWidth = self.getColumnWidth(schemaIndex);
5233
+ column = s[schemaIndex];
5234
+ if (!column.hidden && !isColumnCollapsed(columnIndex)) accumulator += columnWidth;
4279
5235
 
4280
- if (column.hidden) {
5236
+ if (columnIndex < self.frozenColumn) {
4281
5237
  self.scrollCache.x[columnIndex] = accumulator;
4282
- return accumulator;
5238
+ frozenWidth = accumulator;
5239
+ } else {
5240
+ self.scrollCache.x[columnIndex] = Math.max(frozenWidth + columnWidth, accumulator);
4283
5241
  }
4284
5242
 
4285
- var va = accumulator + self.getColumnWidth(self.orders.columns[columnIndex]);
4286
- self.scrollCache.x[columnIndex] = va;
4287
- return va;
5243
+ return accumulator;
4288
5244
  }, 0) || 0;
4289
5245
 
4290
5246
  if (self.attributes.showNewRow) {
@@ -4309,8 +5265,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4309
5265
  // non-controversial
4310
5266
 
4311
5267
 
4312
- self.scrollBox.top = columnHeaderCellHeight + columnHeaderCellBorder;
4313
- self.scrollBox.left = rowHeaderCellWidth; // width and height of scroll box
5268
+ self.scrollBox.top = columnHeaderCellHeight + topGroupAreaHeight + columnHeaderCellBorder;
5269
+ self.scrollBox.left = rowHeaderCellWidth + leftGroupAreaWidth; // width and height of scroll box
4314
5270
 
4315
5271
  setScrollBoxSize(); // is the data larger than the scroll box
4316
5272
 
@@ -4356,24 +5312,24 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4356
5312
  // the dragged mouse.
4357
5313
  // https://github.com/TonyGermaneri/canvas-datagrid/issues/97
4358
5314
 
4359
- self.scrollBox.heightBoxRatio = (self.scrollBox.height - columnHeaderCellHeight - self.scrollCache.y[self.frozenRow]) / dataHeight;
5315
+ self.scrollBox.heightBoxRatio = (self.scrollBox.height - columnHeaderCellHeight - topGroupAreaHeight - self.scrollCache.y[self.frozenRow]) / dataHeight;
4360
5316
  self.scrollBox.scrollBoxHeight = self.scrollBox.height * self.scrollBox.heightBoxRatio - self.style.scrollBarWidth - b - d;
4361
5317
  self.scrollBox.scrollBoxWidth = Math.max(self.scrollBox.scrollBoxWidth, self.style.scrollBarBoxMinSize);
4362
5318
  self.scrollBox.scrollBoxHeight = Math.max(self.scrollBox.scrollBoxHeight, self.style.scrollBarBoxMinSize); // horizontal
4363
5319
 
4364
5320
  n.x += rowHeaderCellWidth;
4365
- n.y += self.height - self.style.scrollBarWidth - d;
4366
- n.width = self.width - self.style.scrollBarWidth - rowHeaderCellWidth - d - m;
5321
+ n.y += self.height - self.style.scrollBarWidth - d - topGroupAreaHeight;
5322
+ n.width = self.width - self.style.scrollBarWidth - rowHeaderCellWidth - leftGroupAreaWidth - d - m;
4367
5323
  n.height = self.style.scrollBarWidth + self.style.scrollBarBorderWidth + d; // horizontal box
4368
5324
 
4369
5325
  nb.y = n.y + self.style.scrollBarBoxMargin;
4370
5326
  nb.width = self.scrollBox.scrollBoxWidth;
4371
5327
  nb.height = self.style.scrollBarBoxWidth; // vertical
4372
5328
 
4373
- v.x += self.width - self.style.scrollBarWidth - self.style.scrollBarBorderWidth - d;
5329
+ v.x += self.width - leftGroupAreaWidth - self.style.scrollBarWidth - self.style.scrollBarBorderWidth - d;
4374
5330
  v.y += columnHeaderCellHeight + self.scrollCache.y[self.frozenRow];
4375
5331
  v.width = self.style.scrollBarWidth + self.style.scrollBarBorderWidth + d;
4376
- v.height = self.height - columnHeaderCellHeight - self.style.scrollBarWidth - d - m; // vertical box
5332
+ v.height = self.height - columnHeaderCellHeight - topGroupAreaHeight - self.style.scrollBarWidth - d - m; // vertical box
4377
5333
 
4378
5334
  vb.x = v.x + self.style.scrollBarBoxMargin;
4379
5335
  vb.y += self.scrollCache.y[self.frozenRow];
@@ -4476,6 +5432,13 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4476
5432
  self.mousemove = function (e, overridePos) {
4477
5433
  if (self.contextMenu || self.input) {
4478
5434
  return;
5435
+ } // Cancel dragging action if user ventures outside grid
5436
+
5437
+
5438
+ if (self.draggingItem && e.which === 0) {
5439
+ self.stopFreezeMove(e);
5440
+ self.mouseup(e);
5441
+ return;
4479
5442
  }
4480
5443
 
4481
5444
  self.mouse = overridePos || self.getLayerPos(e);
@@ -4535,13 +5498,26 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4535
5498
  self.hovers = {
4536
5499
  rowIndex: cell.rowIndex,
4537
5500
  columnIndex: cell.columnIndex,
4538
- onFilterButton: false
5501
+ onFilterButton: false,
5502
+ onCellTreeIcon: false
4539
5503
  };
4540
5504
 
4541
5505
  if (cell.isFilterable && x > cell.x + cell.width + self.canvasOffsetLeft - self.style.filterButtonWidth && x < cell.x + cell.width + self.canvasOffsetLeft && y > cell.y + cell.height + self.canvasOffsetTop - self.style.filterButtonHeight && y < cell.y + cell.height + self.canvasOffsetTop) {
4542
5506
  self.hovers.onFilterButton = true;
4543
5507
  self.draw();
4544
5508
  }
5509
+
5510
+ if (cell.isRowTree || cell.isColumnTree) {
5511
+ var pc = cell.isRowTree ? self.cellTree.rows[cell.rowIndex].parentCount : 0;
5512
+ var rc = self.style.cellTreeIconWidth * self.scale,
5513
+ rx = cell.x + cell.paddingLeft + self.canvasOffsetLeft + self.style.cellTreeIconMarginLeft + pc * (rc + cell.paddingLeft),
5514
+ ry = cell.y + self.canvasOffsetTop + self.style.cellTreeIconMarginTop * self.scale;
5515
+
5516
+ if (x >= rx && x <= rx + rc && y >= ry && y < ry + rc) {
5517
+ self.hovers.onCellTreeIcon = true;
5518
+ self.draw();
5519
+ }
5520
+ }
4545
5521
  }
4546
5522
 
4547
5523
  if (self.selecting || self.reorderObject) {
@@ -4570,6 +5546,16 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4570
5546
  dragBounds.right = s.length - 1;
4571
5547
  dragBounds.top = Math.min(sBounds.top, cell.rowIndex);
4572
5548
  dragBounds.bottom = Math.max(sBounds.bottom, cell.rowIndex);
5549
+ if (dragBounds.top < 0) dragBounds.top = 0;
5550
+ }
5551
+
5552
+ if (self.dragStartObject.rowIndex === -1) {
5553
+ sBounds = self.getSelectionBounds();
5554
+ dragBounds.left = cell.columnIndex === undefined ? sBounds.left : Math.min(sBounds.left, cell.columnIndex);
5555
+ dragBounds.right = cell.columnIndex === undefined ? sBounds.right : Math.max(sBounds.right, cell.columnIndex);
5556
+ dragBounds.top = -1;
5557
+ dragBounds.bottom = self.viewData.length - 1;
5558
+ if (dragBounds.left < 0) dragBounds.left = 0;
4573
5559
  }
4574
5560
 
4575
5561
  if (self.dragStartObject.rowIndex !== cell.rowIndex || self.dragStartObject.columnIndex !== cell.columnIndex) {
@@ -4577,8 +5563,22 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4577
5563
  }
4578
5564
 
4579
5565
  if (self.cellBoundaryCrossed || delta.x === 0 && delta.y === 0 || self.attributes.selectionMode === 'row') {
4580
- if ((self.attributes.selectionMode === 'row' || self.dragStartObject.columnIndex === -1) && self.rowBoundaryCrossed) {
4581
- self.selectRow(cell.rowIndex, ctrl, null, true);
5566
+ if (cell.rowIndex !== undefined && (self.attributes.selectionMode === 'row' || self.dragStartObject.columnIndex === -1) && self.rowBoundaryCrossed) {
5567
+ if (self.dragStartObject.rowIndex < cell.rowIndex) {
5568
+ dragBounds.top = self.dragStartObject.rowIndex;
5569
+ dragBounds.bottom = cell.rowIndex;
5570
+ } else {
5571
+ dragBounds.top = cell.rowIndex;
5572
+ dragBounds.bottom = self.dragStartObject.rowIndex;
5573
+ }
5574
+ } else if (cell.rowIndex !== undefined && (self.attributes.selectionMode === 'column' || self.dragStartObject.rowIndex === -1) && self.columnBoundaryCrossed) {
5575
+ if (self.dragStartObject.columnIndex < cell.columnIndex) {
5576
+ dragBounds.left = self.dragStartObject.columnIndex;
5577
+ dragBounds.right = cell.columnIndex;
5578
+ } else {
5579
+ dragBounds.left = cell.columnIndex;
5580
+ dragBounds.right = self.dragStartObject.columnIndex;
5581
+ }
4582
5582
  } else if (self.attributes.selectionMode !== 'row') {
4583
5583
  if (cell.hovered && self.hovers.onFilterButton) {
4584
5584
  if (cell.openedFilter) {
@@ -4602,12 +5602,16 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4602
5602
 
4603
5603
  self.draw();
4604
5604
  return;
5605
+ } else if (cell.hovered && self.hovers.onCellTreeIcon && e.type == 'mousedown') {
5606
+ self.toggleCollapseTree(cell.rowIndex, cell.columnIndex);
5607
+ return;
4605
5608
  } else {
4606
5609
  self.selectedFilterButton = {
4607
5610
  columnIndex: -1,
4608
5611
  rowIndex: -1
4609
5612
  };
4610
5613
  if (self.hovers.onFilterButton) return;
5614
+ if (self.hovers.onCellTreeIcon) return;
4611
5615
 
4612
5616
  if (!self.dragAddToSelection && cell.rowIndex !== undefined) {
4613
5617
  if (self.selections[cell.rowIndex] && self.selections[cell.rowIndex].indexOf(cell.columnIndex) !== -1) {
@@ -4662,6 +5666,10 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4662
5666
  }
4663
5667
  }
4664
5668
 
5669
+ var columnGroup = self.getColumnGroupAt(self.mouse.x, self.mouse.y);
5670
+ if (columnGroup) self.cursor = 'pointer';
5671
+ var rowGroup = self.getRowGroupAt(self.mouse.x, self.mouse.y);
5672
+ if (rowGroup) self.cursor = 'pointer';
4665
5673
  self.cellBoundaryCrossed = false;
4666
5674
  self.rowBoundaryCrossed = false;
4667
5675
  self.columnBoundaryCrossed = false;
@@ -4718,10 +5726,26 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4718
5726
  return;
4719
5727
  }
4720
5728
 
5729
+ var group = self.getColumnGroupAt(pos.x, pos.y);
5730
+ if (!group) group = self.getRowGroupAt(pos.x, pos.y);
5731
+
5732
+ if (group) {
5733
+ if (self.toggleGroup(group)) {
5734
+ self.setStorageData();
5735
+ self.refresh();
5736
+ return;
5737
+ }
5738
+ }
5739
+
4721
5740
  if (!self.hasFocus) {
4722
5741
  return;
4723
5742
  }
4724
5743
 
5744
+ var leftOffset = self.getRowGroupAreaWidth();
5745
+ var topOffset = self.getColumnGroupAreaHeight();
5746
+ var xInGrid = pos.x - leftOffset;
5747
+ var yInGrid = pos.y - topOffset;
5748
+
4725
5749
  if (['rowHeaderCell', 'columnHeaderCell'].indexOf(self.currentCell.style) === -1 && !ctrl) {
4726
5750
  if (!self.hovers.onFilterButton) {
4727
5751
  self.setActiveCell(i.columnIndex, i.rowIndex);
@@ -4753,7 +5777,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4753
5777
  self.selections[i.rowIndex] = self.selections[i.rowIndex] || [];
4754
5778
 
4755
5779
  if (self.attributes.selectionMode === 'row' || self.currentCell.style === 'rowHeaderCell') {
4756
- if (self.currentCell.style === 'rowHeaderCell' && self.attributes.tree && pos.x > 0 && pos.x - self.currentCell.x < self.style.treeArrowWidth + self.style.treeArrowMarginLeft + self.style.treeArrowMarginRight + self.style.treeArrowClickRadius && pos.y - self.currentCell.y < self.style.treeArrowHeight + self.style.treeArrowMarginTop + self.style.treeArrowClickRadius && pos.y > 0) {
5780
+ if (self.currentCell.style === 'rowHeaderCell' && self.attributes.tree && xInGrid > 0 && xInGrid - self.currentCell.x < self.style.treeArrowWidth + self.style.treeArrowMarginLeft + self.style.treeArrowMarginRight + self.style.treeArrowClickRadius && yInGrid - self.currentCell.y < self.style.treeArrowHeight + self.style.treeArrowMarginTop + self.style.treeArrowClickRadius && yInGrid > 0) {
4757
5781
  self.toggleTree(i.rowIndex);
4758
5782
  return;
4759
5783
  }
@@ -4793,7 +5817,6 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4793
5817
 
4794
5818
  if (self.scrollBox.scrollLeft > self.scrollBox.scrollWidth - self.attributes.resizeScrollZone && self.dragMode === 'ew-resize') {
4795
5819
  self.resize(true);
4796
- self.scrollBox.scrollLeft += x;
4797
5820
  }
4798
5821
 
4799
5822
  if (self.dragMode === 'ew-resize') {
@@ -4959,6 +5982,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4959
5982
  if (Math.abs(x) > self.attributes.reorderDeadZone || Math.abs(y) > self.attributes.reorderDeadZone) {
4960
5983
  self.reorderObject = self.draggingItem;
4961
5984
  if (self.isMultiRowsSelected) self.reorderObject = self.getVisibleCellByIndex(-1, self.activeCell.rowIndex);
5985
+ if (!self.reorderObject) return;
4962
5986
  self.reorderTarget = self.currentCell;
4963
5987
  self.reorderObject.dragOffset = {
4964
5988
  x: x,
@@ -5105,6 +6129,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
5105
6129
  rowHeaderCellWidth = self.getRowHeaderCellWidth();
5106
6130
  self.ignoreNextClick = true;
5107
6131
  self.freezeMarkerPosition = pos;
6132
+ pos.x -= self.getRowGroupAreaWidth();
6133
+ pos.y -= self.getColumnGroupAreaHeight();
5108
6134
 
5109
6135
  if (self.currentCell && self.currentCell.rowIndex !== undefined && self.dragMode === 'frozen-row-marker') {
5110
6136
  self.scrollBox.scrollTop = 0;
@@ -5219,6 +6245,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
5219
6245
 
5220
6246
  if ((self.attributes.selectionMode === 'row' || self.dragStartObject.columnIndex === -1) && self.dragStartObject.rowIndex > -1) {
5221
6247
  self.selectRow(self.dragStartObject.rowIndex, ctrl, null);
6248
+ } else if ((self.attributes.selectionMode === 'column' || self.dragStartObject.rowIndex === -1) && self.dragStartObject.columnIndex > -1) {
6249
+ self.selectColumn(self.currentCell.header.index, ctrl, e.shiftKey);
5222
6250
  } else if (self.attributes.selectionMode !== 'row') {
5223
6251
  self.mousemove(e);
5224
6252
  }
@@ -5603,8 +6631,13 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
5603
6631
  }
5604
6632
  } else if (self.currentCell.context === 'ew-resize' && self.currentCell.style === 'cornerCell') {
5605
6633
  self.autosize();
5606
- } else if (['cell', 'activeCell'].includes(self.currentCell.style) && !self.hovers.onFilterButton) {
5607
- self.beginEditAt(self.currentCell.columnIndex, self.currentCell.rowIndex);
6634
+ } else if (['cell', 'activeCell'].includes(self.currentCell.style) && !self.hovers.onFilterButton && !self.hovers.onCellTreeIcon) {
6635
+ if (self.currentCell.isRowTree || self.currentCell.isColumnTree) {
6636
+ self.cellTreeExpandCollapse(self.currentCell.rowIndex, self.currentCell.columnIndex);
6637
+ self.draw();
6638
+ } else {
6639
+ self.beginEditAt(self.currentCell.columnIndex, self.currentCell.rowIndex);
6640
+ }
5608
6641
  }
5609
6642
  };
5610
6643
 
@@ -6006,7 +7039,7 @@ var parseData = function parseData(data, mimeType) {
6006
7039
  };
6007
7040
 
6008
7041
  var htmlSafe = function htmlSafe(value) {
6009
- if (typeof value === 'number') return value;
7042
+ if (typeof value !== 'string') return value;
6010
7043
  return value.replace(/</g, '&lt;').replace(/>/g, '&gt;');
6011
7044
  };
6012
7045
 
@@ -6028,7 +7061,7 @@ var createHTMLString = function createHTMLString(selectedData, isNeat) {
6028
7061
  var htmlString = '<table>';
6029
7062
  htmlString += selectedData.map(function (row) {
6030
7063
  return '<tr>' + Object.values(row).map(function (value) {
6031
- return '<td>' + htmlSafe(value) + '</td>';
7064
+ return ['<td>', htmlSafe(value), '</td>'].join('');
6032
7065
  }).join('') + '</tr>';
6033
7066
  }).join('');
6034
7067
  htmlString += '</table>';
@@ -6060,6 +7093,14 @@ __webpack_require__.r(__webpack_exports__);
6060
7093
  /*globals HTMLElement: false, Reflect: false, define: true, MutationObserver: false, requestAnimationFrame: false, performance: false, btoa: false*/
6061
7094
 
6062
7095
 
7096
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
7097
+
7098
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
7099
+
7100
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
7101
+
7102
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
7103
+
6063
7104
  function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
6064
7105
 
6065
7106
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
@@ -6130,6 +7171,21 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6130
7171
  self.scrollBox = {};
6131
7172
  self.visibleRows = [];
6132
7173
  self.visibleCells = [];
7174
+ /**
7175
+ * This array stored all groups information with context for drawing,
7176
+ * it is generated by drawing functions,
7177
+ * and be used for searching groups when users operate on the spreadsheet
7178
+ * Each item of this array contains these properties:
7179
+ * - `type`: its available values: 'c' and 'r'. indicates the type of this item, 'c' for column group
7180
+ * and 'r' for row group.
7181
+ * - `x`,`y`: the left-top point of this group's rendering area.
7182
+ * - `x2`, `y2`: the right-bottom of this group's rendering area.
7183
+ * - `collapsed`: this value indicates the collapsed status of this group.
7184
+ * - `from`, `to`: The column index range of this group (We use this value for searching the group)
7185
+ * - `row`: The row index for column groups (We use this value for searching the group)
7186
+ */
7187
+
7188
+ self.visibleGroups = [];
6133
7189
  self.sizes = {
6134
7190
  rows: {},
6135
7191
  columns: {},
@@ -6144,6 +7200,18 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6144
7200
  columnIndex: -1,
6145
7201
  rowIndex: -1
6146
7202
  };
7203
+ self.cellTree = {
7204
+ rows: [],
7205
+ columns: {},
7206
+ tempSchema: {},
7207
+ rowTreeColIndex: 0,
7208
+ columnTreeRowStartIndex: 0,
7209
+ columnTreeRowEndIndex: 0,
7210
+ origin: {
7211
+ rows: [],
7212
+ columns: {}
7213
+ }
7214
+ };
6147
7215
  self.hovers = {};
6148
7216
  self.attributes = {};
6149
7217
  self.style = {};
@@ -6159,9 +7227,31 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6159
7227
  self.scrollPixelLeft = 0;
6160
7228
  self.childGrids = {};
6161
7229
  self.openChildren = {};
7230
+ /**
7231
+ * Array for grouped columns
7232
+ * Each item in this array is an array and it represents some grouping in one row
7233
+ * A grouping descriptor has three properties:
7234
+ * - `from`: The column index of the first column
7235
+ * - `to`: The column index of the last column
7236
+ * - `collapsed`: Is this group be collapsed
7237
+ * @example [[{ from: 1, to: 2, collapsed: false }]]
7238
+ */
7239
+
7240
+ self.groupedColumns = [];
7241
+ /**
7242
+ * Array for grouped rows
7243
+ * Each item in this array is an array and it represents some grouping in one column
7244
+ * A grouping descriptor has three properties:
7245
+ * - `from`: The row index of the first row
7246
+ * - `to`: The row index of the last row
7247
+ * - `collapsed`: Is this group be collapsed
7248
+ * @example [[{ from: 1, to: 2, collapsed: false }]]
7249
+ */
7250
+
7251
+ self.groupedRows = [];
6162
7252
  self.scrollModes = ['vertical-scroll-box', 'vertical-scroll-top', 'vertical-scroll-bottom', 'horizontal-scroll-box', 'horizontal-scroll-right', 'horizontal-scroll-left'];
6163
7253
  self.componentL1Events = {};
6164
- self.eventNames = ['afterdraw', 'afterrendercell', 'afterrenderfilterbutton', 'attributechanged', 'beforebeginedit', 'beforecreatecellgrid', 'beforedraw', 'beforeendedit', 'beforerendercell', 'beforerendercellgrid', 'beforerenderfilterbutton', 'beginedit', 'cellmouseout', 'cellmouseover', 'click', 'collapsetree', 'contextmenu', 'copy', 'datachanged', 'dblclick', 'endedit', 'expandtree', 'formatcellvalue', 'keydown', 'keypress', 'keyup', 'mousedown', 'mousemove', 'mouseup', 'newrow', 'ordercolumn', 'rendercell', 'rendercellgrid', 'renderorderbyarrow', 'rendertext', 'rendertreearrow', 'reorder', 'reordering', 'resize', 'resizecolumn', 'resizerow', 'schemachanged', 'scroll', 'selectionchanged', 'stylechanged', 'touchcancel', 'touchend', 'touchmove', 'touchstart', 'wheel'];
7254
+ self.eventNames = ['afterdraw', 'afterrendercell', 'afterrenderfilterbutton', 'aftercreategroup', 'attributechanged', 'beforebeginedit', 'beforecreatecellgrid', 'beforedraw', 'beforeendedit', 'beforerendercell', 'beforerendercellgrid', 'beforerenderfilterbutton', 'beginedit', 'cellmouseout', 'cellmouseover', 'click', 'collapsetree', 'contextmenu', 'copy', 'datachanged', 'dblclick', 'endedit', 'expandtree', 'formatcellvalue', 'keydown', 'keypress', 'keyup', 'mousedown', 'mousemove', 'mouseup', 'newrow', 'ordercolumn', 'rendercell', 'rendercellgrid', 'renderorderbyarrow', 'rendertext', 'rendertreearrow', 'reorder', 'reordering', 'resize', 'resizecolumn', 'resizerow', 'schemachanged', 'scroll', 'selectionchanged', 'stylechanged', 'touchcancel', 'touchend', 'touchmove', 'touchstart', 'wheel'];
6165
7255
  self.mouse = {
6166
7256
  x: 0,
6167
7257
  y: 0
@@ -6379,7 +7469,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6379
7469
  if (columnIndex < 0) continue;
6380
7470
  var boundColumnIndex = self.getBoundColumnIndexFromViewColumnIndex(columnIndex);
6381
7471
  var columnName = schema[boundColumnIndex].name;
6382
- self.viewData[boundRowIndex][columnName] = '';
7472
+ self.originalData[boundRowIndex][columnName] = '';
6383
7473
  affectedCells.push([rowIndex, columnIndex, boundRowIndex, boundColumnIndex]);
6384
7474
  }
6385
7475
  } catch (err) {
@@ -6408,6 +7498,166 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6408
7498
  self.getBoundColumnIndexFromViewColumnIndex = function (viewColumnIndex) {
6409
7499
  return self.orders.columns[viewColumnIndex];
6410
7500
  };
7501
+ /**
7502
+ * Get the height of the area about column groups for rendering and handling events.
7503
+ */
7504
+
7505
+
7506
+ self.getColumnGroupAreaHeight = function () {
7507
+ if (!self.attributes.allowGroupingColumns) {
7508
+ return 0;
7509
+ }
7510
+
7511
+ var groups = self.groupedColumns.length;
7512
+ var base = self.style.columnGroupRowHeight * self.scale;
7513
+ return base * groups;
7514
+ };
7515
+ /**
7516
+ * Get the width of the area about row groups for rendering and handling events.
7517
+ */
7518
+
7519
+
7520
+ self.getRowGroupAreaWidth = function () {
7521
+ if (!self.attributes.allowGroupingRows) {
7522
+ return 0;
7523
+ }
7524
+
7525
+ var groups = self.groupedRows.length;
7526
+ var base = self.style.rowGroupColumnWidth * self.scale;
7527
+ return base * groups;
7528
+ };
7529
+
7530
+ self.getCollapsedColumnGroups = function () {
7531
+ var result = [];
7532
+
7533
+ for (var rowIndex = 0; rowIndex < self.groupedColumns.length; rowIndex++) {
7534
+ var groups = self.groupedColumns[rowIndex];
7535
+
7536
+ for (var groupIndex = 0; groupIndex < groups.length; groupIndex++) {
7537
+ var group = groups[groupIndex];
7538
+ if (group.collapsed) result.push(group);
7539
+ }
7540
+ }
7541
+
7542
+ return result;
7543
+ };
7544
+
7545
+ self.getCollapsedRowGroups = function () {
7546
+ var result = [];
7547
+
7548
+ for (var rowIndex = 0; rowIndex < self.groupedRows.length; rowIndex++) {
7549
+ var groups = self.groupedRows[rowIndex];
7550
+
7551
+ for (var groupIndex = 0; groupIndex < groups.length; groupIndex++) {
7552
+ var group = groups[groupIndex];
7553
+ if (group.collapsed) result.push(group);
7554
+ }
7555
+ }
7556
+
7557
+ return result;
7558
+ };
7559
+ /**
7560
+ * Toggle the collapse status of a group (expanded/collapsed)
7561
+ * @param {{type:string,from:number,to:number}} group
7562
+ */
7563
+
7564
+
7565
+ self.toggleGroup = function (group) {
7566
+ if (group.type === 'c') {
7567
+ var from = group.from,
7568
+ to = group.to;
7569
+ /** @type {{from:number,to:number,collapsed:boolean}} */
7570
+
7571
+ var matchedGroup;
7572
+ /** @type {Array<Array<{from:number,to:number,collapsed:boolean}>>} */
7573
+
7574
+ var allGroups = self.groupedColumns;
7575
+
7576
+ for (var i = 0; i < allGroups.length; i++) {
7577
+ var groups = allGroups[i];
7578
+
7579
+ for (var gi = 0; gi < groups.length; gi++) {
7580
+ var _group = groups[gi];
7581
+
7582
+ if (_group.from === from && _group.to === to) {
7583
+ matchedGroup = _group;
7584
+ break;
7585
+ }
7586
+ }
7587
+
7588
+ if (matchedGroup) break;
7589
+ }
7590
+
7591
+ if (!matchedGroup) return;
7592
+ var nextCollapsed = !matchedGroup.collapsed;
7593
+ matchedGroup.collapsed = nextCollapsed;
7594
+ return true;
7595
+ }
7596
+
7597
+ if (group.type === 'r') {
7598
+ var _from = group.from,
7599
+ _to = group.to;
7600
+ /** @type {{from:number,to:number,collapsed:boolean}} */
7601
+
7602
+ var _matchedGroup;
7603
+ /** @type {Array<Array<{from:number,to:number,collapsed:boolean}>>} */
7604
+
7605
+
7606
+ var _allGroups = self.groupedRows;
7607
+
7608
+ for (var _i3 = 0; _i3 < _allGroups.length; _i3++) {
7609
+ var _groups = _allGroups[_i3];
7610
+
7611
+ for (var _gi = 0; _gi < _groups.length; _gi++) {
7612
+ var _group2 = _groups[_gi];
7613
+
7614
+ if (_group2.from === _from && _group2.to === _to) {
7615
+ _matchedGroup = _group2;
7616
+ break;
7617
+ }
7618
+ }
7619
+
7620
+ if (_matchedGroup) break;
7621
+ }
7622
+
7623
+ if (!_matchedGroup) return;
7624
+
7625
+ var _nextCollapsed = !_matchedGroup.collapsed;
7626
+
7627
+ _matchedGroup.collapsed = _nextCollapsed;
7628
+ return true;
7629
+ }
7630
+
7631
+ return false;
7632
+ };
7633
+
7634
+ self.isNewGroupRangeValid = function (groupsArray, from, to) {
7635
+ for (var i = 0; i < groupsArray.length; i++) {
7636
+ var groups = groupsArray[i];
7637
+
7638
+ for (var gIndex = 0; gIndex < groups.length; gIndex++) {
7639
+ var group = groups[gIndex];
7640
+ if (from === group.to + 1) return false;
7641
+ if (from > group.to) continue;
7642
+
7643
+ if (from === group.from) {
7644
+ if (to === group.to) return false;
7645
+ if (to > group.to) return true;
7646
+ break; // check smaller range
7647
+ }
7648
+
7649
+ if (from > group.from) {
7650
+ if (to > group.to) return false;
7651
+ break; // check smaller range
7652
+ }
7653
+
7654
+ if (to < group.to) return false;
7655
+ return true;
7656
+ }
7657
+ }
7658
+
7659
+ return true;
7660
+ };
6411
7661
 
6412
7662
  self.getColumnHeaderCellHeight = function () {
6413
7663
  if (!self.attributes.showColumnHeaders) {
@@ -6560,6 +7810,19 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6560
7810
  return self.columnFilters && Object.keys(self.columnFilters).length > 0;
6561
7811
  };
6562
7812
 
7813
+ self.hasCollapsedRowGroup = function () {
7814
+ for (var i = 0; i < self.groupedRows.length; i++) {
7815
+ var groups = self.groupedRows[i];
7816
+
7817
+ for (var j = 0; j < groups.length; j++) {
7818
+ var g = groups[j];
7819
+ if (g.collapsed) return true;
7820
+ }
7821
+ }
7822
+
7823
+ return false;
7824
+ };
7825
+
6563
7826
  self.getFilteredAndSortedViewData = function (originalData) {
6564
7827
  // We make a copy of originalData here in order be able to
6565
7828
  // filter and sort rows without modifying the original array.
@@ -6572,7 +7835,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6572
7835
  }); // Apply filtering
6573
7836
 
6574
7837
  var _loop = function _loop() {
6575
- var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i3], 2),
7838
+ var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i4], 2),
6576
7839
  headerName = _Object$entries2$_i[0],
6577
7840
  filterText = _Object$entries2$_i[1];
6578
7841
 
@@ -6593,11 +7856,81 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6593
7856
  });
6594
7857
  };
6595
7858
 
6596
- for (var _i3 = 0, _Object$entries2 = Object.entries(self.columnFilters); _i3 < _Object$entries2.length; _i3++) {
7859
+ for (var _i4 = 0, _Object$entries2 = Object.entries(self.columnFilters); _i4 < _Object$entries2.length; _i4++) {
6597
7860
  var _ret = _loop();
6598
7861
 
6599
7862
  if (_ret === "continue") continue;
6600
- } // Apply sorting
7863
+ } //#region Hide rows from collapsed group
7864
+
7865
+ /** @type {number[][]} */
7866
+
7867
+
7868
+ var collapsedGroups = [];
7869
+
7870
+ for (var i = 0; i < self.groupedRows.length; i++) {
7871
+ var rows = self.groupedRows[i];
7872
+
7873
+ for (var j = 0; j < rows.length; j++) {
7874
+ var r = rows[j];
7875
+ if (!r.collapsed) continue;
7876
+ collapsedGroups.push([r.from, r.to]);
7877
+ }
7878
+ }
7879
+
7880
+ if (collapsedGroups.length > 0) {
7881
+ //#region merge groups
7882
+ collapsedGroups.sort(function (a, b) {
7883
+ return a[0] - b[0];
7884
+ });
7885
+ var newLen = 0;
7886
+ var len = collapsedGroups.length;
7887
+
7888
+ for (var _i5 = 0; _i5 < len; _i5++) {
7889
+ var _r = collapsedGroups[_i5];
7890
+
7891
+ if (_i5 === len - 1) {
7892
+ collapsedGroups[newLen++] = _r;
7893
+ break;
7894
+ }
7895
+
7896
+ var to = _r[1];
7897
+
7898
+ var _collapsedGroups = _slicedToArray(collapsedGroups[_i5 + 1], 2),
7899
+ from2 = _collapsedGroups[0],
7900
+ to2 = _collapsedGroups[1];
7901
+
7902
+ if (from2 > to + 1) {
7903
+ collapsedGroups[newLen++] = _r;
7904
+ continue;
7905
+ }
7906
+
7907
+ collapsedGroups[_i5 + 1] = _r;
7908
+ if (to2 > to) collapsedGroups[_i5 + 1][1] = to2;
7909
+ }
7910
+
7911
+ collapsedGroups = collapsedGroups.slice(0, newLen); //#endregion merge groups
7912
+ //#region omit rows by groups
7913
+
7914
+ var g = collapsedGroups.shift();
7915
+
7916
+ for (var start = 0; start < newViewData.length; start++) {
7917
+ var it = newViewData[start][1];
7918
+ if (it < g[0]) continue;
7919
+ var end = start + 1;
7920
+
7921
+ for (; end < newViewData.length; end++) {
7922
+ var it2 = newViewData[end][1];
7923
+ if (it2 > g[1]) break;
7924
+ }
7925
+
7926
+ newViewData.splice(start, end - start);
7927
+ g = collapsedGroups.shift();
7928
+ if (!g) break;
7929
+ start--;
7930
+ } //#endregion omit rows by groups
7931
+
7932
+ } //#endregion Hide rows from collapsed group
7933
+ // Apply sorting
6601
7934
 
6602
7935
 
6603
7936
  var _iterator8 = _createForOfIteratorHelper(self.orderings.columns),
@@ -6812,6 +8145,329 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6812
8145
  }
6813
8146
  };
6814
8147
 
8148
+ self.toggleCollapseTree = function (rowIndex, columnIndex, type) {
8149
+ var tempData = [];
8150
+ var collapsedCount = 0;
8151
+
8152
+ if (columnIndex == self.cellTree.rowTreeColIndex && (rowIndex > 0 || rowIndex == 0 && self.cellTree.rows[0].icon)) {
8153
+ var ctr = self.cellTree.rows;
8154
+
8155
+ switch (type) {
8156
+ case 'Expand':
8157
+ ctr[rowIndex].expand = true;
8158
+ self.cellTree.origin.rows[ctr[rowIndex].index].expand = true;
8159
+ break;
8160
+
8161
+ case 'Collapse':
8162
+ ctr[rowIndex].expand = false;
8163
+ self.cellTree.origin.rows[ctr[rowIndex].index].expand = false;
8164
+ break;
8165
+
8166
+ default:
8167
+ ctr[rowIndex].expand = !ctr[rowIndex].expand;
8168
+ self.cellTree.origin.rows[ctr[rowIndex].index].expand = ctr[rowIndex].expand;
8169
+ }
8170
+
8171
+ for (var ri = ctr[rowIndex].index + 1; ri <= ctr[rowIndex].lastchild; ri++) {
8172
+ var orTree = self.cellTree.origin.rows[ri];
8173
+
8174
+ if (ctr[rowIndex].expand) {
8175
+ orTree.hide = false;
8176
+ if (orTree.icon && !orTree.expand) ri = orTree.lastchild;
8177
+ } else {
8178
+ orTree.hide = true;
8179
+ }
8180
+ }
8181
+ } else if (self.cellTree.columns[rowIndex]) {
8182
+ var ctc = self.cellTree.columns[rowIndex];
8183
+
8184
+ switch (type) {
8185
+ case 'Expand':
8186
+ ctc[columnIndex].expand = true;
8187
+ break;
8188
+
8189
+ case 'Collapse':
8190
+ ctc[columnIndex].expand = false;
8191
+ break;
8192
+
8193
+ default:
8194
+ ctc[columnIndex].expand = !ctc[columnIndex].expand;
8195
+ }
8196
+
8197
+ for (var ci = ctc[columnIndex].index + 1; ci <= ctc[columnIndex].lastchild; ci++) {
8198
+ if (ctc[columnIndex].expand) self.cellTree.tempSchema[ci].hidden = false;else self.cellTree.tempSchema[ci].hidden = true;
8199
+ }
8200
+
8201
+ var rc = 0,
8202
+ _ri;
8203
+
8204
+ if (ctc[columnIndex].expand) {
8205
+ while (rc < ctc[columnIndex].child) {
8206
+ _ri = rowIndex + rc + 1;
8207
+
8208
+ for (var _ci = ctc[columnIndex].index; _ci <= ctc[columnIndex].lastchild; _ci++) {
8209
+ if (self.cellTree.origin.columns[_ri] && self.cellTree.origin.columns[_ri][_ci].icon && !self.cellTree.origin.columns[_ri][_ci].expand) {
8210
+ for (var si = _ci + 1; si <= self.cellTree.origin.columns[_ri][_ci].lastchild; si++) {
8211
+ self.cellTree.tempSchema[si].hidden = true;
8212
+ }
8213
+ }
8214
+ }
8215
+
8216
+ rc++;
8217
+ }
8218
+ }
8219
+ }
8220
+
8221
+ var otherData = {};
8222
+ var collapsed = [];
8223
+ self.cellTree.rows = [];
8224
+ self.cellTree.columns = {};
8225
+
8226
+ for (var k in self.cellTree.origin.rows) {
8227
+ var tempRow = [];
8228
+ var tree = self.cellTree.origin.rows[k];
8229
+
8230
+ if (!tree.hide) {
8231
+ var colTrees = [];
8232
+ var collapsedColCount = 0;
8233
+
8234
+ if (k < self.cellTree.columnTreeRowStartIndex) {
8235
+ tempData.push(self.originalData[k]);
8236
+ } else {
8237
+ if (k > self.cellTree.columnTreeRowEndIndex) {
8238
+ otherData[k] = self.viewData[k];
8239
+ collapsedCount++;
8240
+ } else {
8241
+ for (var l = 0; l < self.originalData[k].length; l++) {
8242
+ if (!self.cellTree.tempSchema[l].hidden) {
8243
+ if (l < self.cellTree.rowTreeColIndex) {
8244
+ if (!Object.prototype.hasOwnProperty.call(otherData, k)) otherData[k] = [];
8245
+ otherData[k].push(self.viewData[k][l]);
8246
+ }
8247
+
8248
+ tempRow.push(self.originalData[k][l]);
8249
+ if (Object.prototype.hasOwnProperty.call(self.cellTree.origin.columns, k)) colTrees.push(self.cellTree.origin.columns[k][l]);
8250
+ } else collapsedColCount++;
8251
+ }
8252
+
8253
+ tempRow.push.apply(tempRow, _toConsumableArray(Array(collapsedColCount).fill().map(function () {
8254
+ return '';
8255
+ })));
8256
+
8257
+ if (colTrees.length) {
8258
+ colTrees.push.apply(colTrees, _toConsumableArray(Array(collapsedColCount).fill().map(function () {
8259
+ return {};
8260
+ })));
8261
+ self.cellTree.columns[k] = colTrees;
8262
+ }
8263
+
8264
+ tempData.push(tempRow);
8265
+ }
8266
+ }
8267
+
8268
+ self.cellTree.rows.push(tree);
8269
+ } else {
8270
+ for (var _l = 0; _l < self.cellTree.rowTreeColIndex; _l++) {
8271
+ tempRow.push(self.viewData[k][_l]);
8272
+ }
8273
+
8274
+ otherData[k] = tempRow;
8275
+ collapsed.push(Array(self.viewData[0].length).fill().map(function () {
8276
+ return '';
8277
+ }));
8278
+ collapsedCount++;
8279
+ }
8280
+ }
8281
+
8282
+ if (collapsedCount) {
8283
+ var _self$cellTree$rows;
8284
+
8285
+ (_self$cellTree$rows = self.cellTree.rows).push.apply(_self$cellTree$rows, _toConsumableArray(Array(collapsedCount).fill().map(function (u, index) {
8286
+ return {
8287
+ index: self.cellTree.rows.length + index
8288
+ };
8289
+ })));
8290
+
8291
+ tempData.push.apply(tempData, collapsed);
8292
+ }
8293
+
8294
+ for (var _k in otherData) {
8295
+ if (_k > self.cellTree.columnTreeRowEndIndex) tempData[_k] = otherData[_k];else for (var _l2 in otherData[_k]) {
8296
+ tempData[_k][_l2] = otherData[_k][_l2];
8297
+ }
8298
+ }
8299
+
8300
+ self.viewData = tempData;
8301
+ };
8302
+
8303
+ self.cellTreeExpandCollapse = function (rowIndex, columnIndex, type) {
8304
+ if (columnIndex == self.cellTree.rowTreeColIndex && (rowIndex > 0 || rowIndex == 0 && self.cellTree.rows[0].icon)) {
8305
+ var ctr = self.cellTree.rows;
8306
+
8307
+ switch (type) {
8308
+ case 'Expand':
8309
+ ctr[rowIndex].expand = true;
8310
+ break;
8311
+
8312
+ case 'Collapse':
8313
+ ctr[rowIndex].expand = false;
8314
+ break;
8315
+
8316
+ default:
8317
+ ctr[rowIndex].expand = !ctr[rowIndex].expand;
8318
+ }
8319
+
8320
+ for (var ri = rowIndex + 1; ri <= ctr[rowIndex].lastchild; ri++) {
8321
+ if (ctr[rowIndex].expand) {
8322
+ ctr[ri].hide = false;
8323
+ if (ctr[ri].icon && !ctr[ri].expand) ri = ctr[ri].lastchild;
8324
+ } else {
8325
+ ctr[ri].hide = true;
8326
+ }
8327
+ }
8328
+ } else if (self.cellTree.columns[rowIndex]) {
8329
+ var ctc = self.cellTree.columns[rowIndex];
8330
+
8331
+ switch (type) {
8332
+ case 'Expand':
8333
+ ctc[columnIndex].expand = true;
8334
+ break;
8335
+
8336
+ case 'Collapse':
8337
+ ctc[columnIndex].expand = false;
8338
+ break;
8339
+
8340
+ default:
8341
+ ctc[columnIndex].expand = !ctc[columnIndex].expand;
8342
+ }
8343
+
8344
+ for (var ci = columnIndex + 1; ci <= ctc[columnIndex].lastchild; ci++) {
8345
+ if (ctc[columnIndex].expand) self.tempSchema[ci].hidden = false;else self.tempSchema[ci].hidden = true;
8346
+ }
8347
+
8348
+ var rc = 0,
8349
+ _ri2;
8350
+
8351
+ if (ctc[columnIndex].expand) {
8352
+ while (rc < ctc[columnIndex].child) {
8353
+ _ri2 = rowIndex + rc + 1;
8354
+
8355
+ for (var _ci2 = columnIndex; _ci2 <= ctc[columnIndex].lastchild; _ci2++) {
8356
+ if (self.cellTree.columns[_ri2] && self.cellTree.columns[_ri2][_ci2].icon && !self.cellTree.columns[_ri2][_ci2].expand) {
8357
+ for (var si = _ci2 + 1; si <= self.cellTree.columns[_ri2][_ci2].lastchild; si++) {
8358
+ self.tempSchema[si].hidden = true;
8359
+ }
8360
+ }
8361
+ }
8362
+
8363
+ rc++;
8364
+ }
8365
+ }
8366
+ }
8367
+ };
8368
+
8369
+ self.initCellTreeSettings = function () {
8370
+ if (self.viewData === undefined) return;
8371
+
8372
+ if (self.attributes.rowTree.length > 0 && self.viewData.length > 0) {
8373
+ self.cellTree.rows = Array(self.viewData.length).fill().map(function (u, index) {
8374
+ return {
8375
+ index: index
8376
+ };
8377
+ });
8378
+ self.cellTree.rowTreeColIndex = self.attributes.rowTreeColIndex;
8379
+ var invalidRowTree = false;
8380
+
8381
+ var _iterator9 = _createForOfIteratorHelper(self.attributes.rowTree),
8382
+ _step9;
8383
+
8384
+ try {
8385
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
8386
+ var rt = _step9.value;
8387
+
8388
+ if (self.cellTree.rows.length <= rt.end) {
8389
+ invalidRowTree = true;
8390
+ break;
8391
+ }
8392
+
8393
+ for (var ri = rt.begin; ri <= rt.end; ri++) {
8394
+ if (ri == rt.begin) {
8395
+ self.cellTree.rows[ri].icon = true;
8396
+ self.cellTree.rows[ri].lastchild = rt.end;
8397
+ self.cellTree.rows[ri].expand = true;
8398
+ if (!self.cellTree.rows[ri].parentCount) self.cellTree.rows[ri].parentCount = 0;
8399
+ } else {
8400
+ self.cellTree.rows[ri].hide = false;
8401
+ self.cellTree.rows[ri].parentIndex = rt.begin;
8402
+ if (self.cellTree.rows[ri] && self.cellTree.rows[ri].parentCount) self.cellTree.rows[ri].parentCount += 1;else self.cellTree.rows[ri].parentCount = 1;
8403
+ }
8404
+ }
8405
+ }
8406
+ } catch (err) {
8407
+ _iterator9.e(err);
8408
+ } finally {
8409
+ _iterator9.f();
8410
+ }
8411
+
8412
+ if (invalidRowTree) self.cellTree.rows = {};
8413
+ }
8414
+
8415
+ if (self.attributes.columnTree.length > 0 && self.viewData.length > 0) {
8416
+ self.cellTree.columnTreeRowStartIndex = self.attributes.columnTreeRowStartIndex;
8417
+ self.cellTree.columnTreeRowEndIndex = self.attributes.columnTreeRowEndIndex;
8418
+ var dataColumnLength = Object.keys(self.viewData[0]).length;
8419
+ var invalidColumnTree = false;
8420
+
8421
+ var _iterator10 = _createForOfIteratorHelper(self.attributes.columnTree),
8422
+ _step10;
8423
+
8424
+ try {
8425
+ for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
8426
+ var ct = _step10.value;
8427
+
8428
+ if (dataColumnLength <= ct.end) {
8429
+ invalidColumnTree = true;
8430
+ break;
8431
+ }
8432
+
8433
+ if (!self.cellTree.columns[ct.row]) self.cellTree.columns[ct.row] = Array(dataColumnLength).fill().map(function (u, index) {
8434
+ return {
8435
+ index: index
8436
+ };
8437
+ });
8438
+
8439
+ for (var i = ct.begin; i <= ct.end; i++) {
8440
+ var ctc = self.cellTree.columns[ct.row][i];
8441
+
8442
+ if (i == ct.begin) {
8443
+ ctc.icon = true;
8444
+ ctc.lastchild = ct.end;
8445
+ ctc.length = ct.end - ct.begin;
8446
+ ctc.expand = true;
8447
+ if (ct.child) ctc.child = ct.child;else ctc.child = 0;
8448
+ }
8449
+ }
8450
+ }
8451
+ } catch (err) {
8452
+ _iterator10.e(err);
8453
+ } finally {
8454
+ _iterator10.f();
8455
+ }
8456
+
8457
+ self.cellTree.tempSchema = Array(dataColumnLength).fill().map(function () {
8458
+ return {
8459
+ hidden: false
8460
+ };
8461
+ });
8462
+ if (invalidColumnTree) self.cellTree.columns = {};
8463
+ }
8464
+
8465
+ self.cellTree.origin = {
8466
+ rows: self.cellTree.rows,
8467
+ columns: self.cellTree.columns
8468
+ };
8469
+ };
8470
+
6815
8471
  self.getDomRoot = function () {
6816
8472
  return self.shadowRoot ? self.shadowRoot.host : self.parentNode;
6817
8473
  };
@@ -6992,6 +8648,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6992
8648
  self.intf.gotoCell = self.gotoCell;
6993
8649
  self.intf.gotoRow = self.gotoRow;
6994
8650
  self.intf.addButton = self.addButton;
8651
+ self.intf.toggleCellCollapseTree = self.toggleCellCollapseTree;
8652
+ self.intf.expandCollapseCellTree = self.expandCollapseCellTree;
6995
8653
  self.intf.getHeaderByName = self.getHeaderByName;
6996
8654
  self.intf.findColumnScrollLeft = self.findColumnScrollLeft;
6997
8655
  self.intf.findRowScrollTop = self.findRowScrollTop;
@@ -6999,6 +8657,14 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6999
8657
  self.intf.findColumnMaxTextLength = self.findColumnMaxTextLength;
7000
8658
  self.intf.disposeContextMenu = self.disposeContextMenu;
7001
8659
  self.intf.getCellAt = self.getCellAt;
8660
+ self.intf.groupColumns = self.groupColumns;
8661
+ self.intf.groupRows = self.groupRows;
8662
+ self.intf.removeGroupColumns = self.removeGroupColumns;
8663
+ self.intf.removeGroupRows = self.removeGroupRows;
8664
+ self.intf.toggleGroupColumns = self.toggleGroupColumns;
8665
+ self.intf.toggleGroupRows = self.toggleGroupRows;
8666
+ self.intf.getGroupsColumnBelongsTo = self.getGroupsColumnBelongsTo;
8667
+ self.intf.getGroupsRowBelongsTo = self.getGroupsRowBelongsTo;
7002
8668
  self.intf.isCellVisible = self.isCellVisible;
7003
8669
  self.intf.isRowVisible = self.isRowVisible;
7004
8670
  self.intf.isColumnVisible = self.isColumnVisible;
@@ -7129,6 +8795,10 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
7129
8795
  self.tryLoadStoredSettings();
7130
8796
  }
7131
8797
 
8798
+ if (key === 'rowTree' || key === 'columnTree' || key === 'columnTreeRowEndIndex') {
8799
+ self.initCellTreeSettings();
8800
+ }
8801
+
7132
8802
  self.draw(true);
7133
8803
  self.dispatchEvent('attributechanged', {
7134
8804
  name: key,
@@ -7763,6 +9433,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
7763
9433
  self.dispatchEvent('datachanged', {
7764
9434
  data: self.originalData
7765
9435
  });
9436
+ self.initCellTreeSettings();
7766
9437
  self.resize(true);
7767
9438
  });
7768
9439
  }
@@ -8112,6 +9783,12 @@ __webpack_require__.r(__webpack_exports__);
8112
9783
  /*globals define: true, MutationObserver: false, requestAnimationFrame: false, performance: false, btoa: false*/
8113
9784
 
8114
9785
 
9786
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
9787
+
9788
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
9789
+
9790
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
9791
+
8115
9792
  /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(self) {
8116
9793
  /**
8117
9794
  * Converts a integer into a letter A - ZZZZZ...
@@ -8458,6 +10135,62 @@ __webpack_require__.r(__webpack_exports__);
8458
10135
  left: cells[0].x + cells[0].width + offset.x
8459
10136
  }, items, imgSrc);
8460
10137
  };
10138
+ /**
10139
+ * Expand/Collapse CellTree.
10140
+ * @memberof canvasDatagrid
10141
+ * @name toggleCellCollapseTree
10142
+ * @method
10143
+ * @param {array} treeData The array of cellTree to expand or collapse.
10144
+ */
10145
+
10146
+
10147
+ self.toggleCellCollapseTree = function (treeData) {
10148
+ for (var type in treeData) {
10149
+ var _iterator = _createForOfIteratorHelper(treeData[type]),
10150
+ _step;
10151
+
10152
+ try {
10153
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
10154
+ var t = _step.value;
10155
+ if (t.length > 0) self.toggleCollapseTree(t[0], t[1], type);
10156
+ }
10157
+ } catch (err) {
10158
+ _iterator.e(err);
10159
+ } finally {
10160
+ _iterator.f();
10161
+ }
10162
+ }
10163
+
10164
+ self.draw();
10165
+ };
10166
+ /**
10167
+ * Expand/Collapse CellTree.
10168
+ * @memberof canvasDatagrid
10169
+ * @name expandCollapseCellTree
10170
+ * @method
10171
+ * @param {array} treeData The array of cellTree to expand or collapse.
10172
+ */
10173
+
10174
+
10175
+ self.expandCollapseCellTree = function (treeData) {
10176
+ for (var type in treeData) {
10177
+ var _iterator2 = _createForOfIteratorHelper(treeData[type]),
10178
+ _step2;
10179
+
10180
+ try {
10181
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
10182
+ var t = _step2.value;
10183
+ if (t.length > 0) self.cellTreeExpandCollapse(t[0], t[1], type);
10184
+ }
10185
+ } catch (err) {
10186
+ _iterator2.e(err);
10187
+ } finally {
10188
+ _iterator2.f();
10189
+ }
10190
+ }
10191
+
10192
+ self.draw();
10193
+ };
8461
10194
  /**
8462
10195
  * Scrolls the cell at cell x, row y into view if it is not already.
8463
10196
  * @memberof canvasDatagrid
@@ -8471,9 +10204,16 @@ __webpack_require__.r(__webpack_exports__);
8471
10204
 
8472
10205
 
8473
10206
  self.scrollIntoView = function (x, y, offsetX, offsetY) {
8474
- if (self.visibleCells.filter(function (cell) {
10207
+ var matched = self.visibleCells.filter(function (cell) {
8475
10208
  return (cell.rowIndex === y || y === undefined) && (cell.columnIndex === x || x === undefined) && cell.x > 0 && cell.y > 0 && cell.x + cell.width < self.width && cell.y + cell.height < self.height;
8476
- }).length === 0) {
10209
+ });
10210
+
10211
+ if (matched.length === 1 && x !== undefined && y !== undefined) {
10212
+ // goto specific cell and its part be hidden by header
10213
+ if (matched[0].x < self.getRowHeaderCellWidth() || matched[0].y < self.getColumnHeaderCellHeight()) matched.length = 0;
10214
+ }
10215
+
10216
+ if (matched.length === 0) {
8477
10217
  self.gotoCell(x, y, offsetX, offsetY);
8478
10218
  }
8479
10219
  };
@@ -9002,6 +10742,315 @@ __webpack_require__.r(__webpack_exports__);
9002
10742
 
9003
10743
  self.setStorageData();
9004
10744
  };
10745
+ /**
10746
+ * Add grouping
10747
+ * @param {'columns'|'rows'} groupFor
10748
+ * @param {number} from
10749
+ * @param {number} to
10750
+ */
10751
+
10752
+
10753
+ function addGroup(groupFor, from, to) {
10754
+ var newRow = false;
10755
+ var allGroups = groupFor === 'rows' ? self.groupedRows : self.groupedColumns;
10756
+
10757
+ for (var i = allGroups.length - 1; i >= 0; i--) {
10758
+ var groups = allGroups[i];
10759
+ var min = groups[0].from,
10760
+ max = groups[groups.length - 1].to;
10761
+
10762
+ if (from <= min && to >= max) {
10763
+ if (from === min && to === max && groups.length === 1) return; // nothings happened
10764
+ // new group wrap this row
10765
+
10766
+ continue;
10767
+ }
10768
+
10769
+ for (var gi = 0; gi < groups.length; gi++) {
10770
+ var g = groups[gi];
10771
+ if (from > g.to) continue;
10772
+
10773
+ if (from >= g.from) {
10774
+ if (to > g.to) {
10775
+ if (from === g.from) {
10776
+ allGroups.splice(i, 0, [{
10777
+ from: from,
10778
+ to: to,
10779
+ collapsed: false
10780
+ }]);
10781
+ self.refresh();
10782
+ return;
10783
+ }
10784
+
10785
+ throw new Error("Can't group these ".concat(groupFor));
10786
+ }
10787
+
10788
+ if (to === g.to) {
10789
+ if (from === g.from) return; // nothings happened
10790
+ }
10791
+
10792
+ newRow = true;
10793
+ break;
10794
+ }
10795
+
10796
+ if (to >= g.from) {
10797
+ if (to < g.to) throw new Error("Can't group these ".concat(groupFor));
10798
+ allGroups.splice(i, 0, [{
10799
+ from: from,
10800
+ to: to,
10801
+ collapsed: false
10802
+ }]);
10803
+ } else {
10804
+ groups.splice(gi, 0, {
10805
+ from: from,
10806
+ to: to,
10807
+ collapsed: false
10808
+ });
10809
+ }
10810
+
10811
+ self.refresh();
10812
+ return;
10813
+ }
10814
+
10815
+ if (newRow) continue;
10816
+ groups.push({
10817
+ from: from,
10818
+ to: to,
10819
+ collapsed: false
10820
+ });
10821
+ self.refresh();
10822
+ return;
10823
+ }
10824
+
10825
+ if (newRow) allGroups.push([{
10826
+ from: from,
10827
+ to: to,
10828
+ collapsed: false
10829
+ }]);else allGroups.unshift([{
10830
+ from: from,
10831
+ to: to,
10832
+ collapsed: false
10833
+ }]);
10834
+ self.refresh();
10835
+ }
10836
+ /**
10837
+ * Remove grouping
10838
+ * @param {Array<Array<{from:number,to:number,collapsed:boolean}>>} allGroups
10839
+ * @param {number} from
10840
+ * @param {number} to
10841
+ */
10842
+
10843
+
10844
+ function removeGroup(allGroups, from, to) {
10845
+ for (var i = 0; i < allGroups.length; i++) {
10846
+ var groups = allGroups[i];
10847
+
10848
+ for (var gi = 0; gi < groups.length; gi++) {
10849
+ var group = groups[gi];
10850
+
10851
+ if (group.from === from && group.to === to) {
10852
+ if (groups.length <= 1) allGroups.splice(i, 1);else groups.splice(gi, 1);
10853
+ self.refresh();
10854
+ return;
10855
+ }
10856
+ }
10857
+ }
10858
+ }
10859
+ /**
10860
+ * Grouping columns
10861
+ * @memberof canvasDatagrid
10862
+ * @name groupColumns
10863
+ * @method
10864
+ * @param {number|string} firstColumnName Name of the first column to be grouped.
10865
+ * @param {number|string} lastColumnName Name of the last column to be grouped.
10866
+ */
10867
+
10868
+
10869
+ self.groupColumns = function (firstColumnName, lastColumnName) {
10870
+ /** @type {Array<{name: string,columnIndex:number}>} */
10871
+ var schema = self.getSchema();
10872
+ var firstOne, lastOne;
10873
+
10874
+ for (var i = 0; i < schema.length; i++) {
10875
+ var it = schema[i];
10876
+ if (firstOne && lastOne) break;
10877
+
10878
+ if (it.name === firstColumnName) {
10879
+ firstOne = it;
10880
+ continue;
10881
+ }
10882
+
10883
+ if (it.name === lastColumnName) {
10884
+ lastOne = it;
10885
+ continue;
10886
+ }
10887
+ }
10888
+
10889
+ if (!firstOne) throw new Error("No such column name for first column");
10890
+ if (!lastOne) throw new Error("No such column name for last column");
10891
+ if (lastOne.columnIndex > firstOne.columnIndex !== true) throw new Error("Can't group these columns");
10892
+ var from = firstOne.columnIndex;
10893
+ var to = lastOne.columnIndex;
10894
+ var ev = {
10895
+ group: {
10896
+ type: 'columns',
10897
+ from: from,
10898
+ to: to
10899
+ }
10900
+ };
10901
+
10902
+ try {
10903
+ addGroup('columns', from, to);
10904
+ } catch (error) {
10905
+ ev.error = error;
10906
+ }
10907
+
10908
+ self.dispatchEvent('aftercreategroup', ev);
10909
+ };
10910
+ /**
10911
+ * Grouping columns
10912
+ * @memberof canvasDatagrid
10913
+ * @name groupRows
10914
+ * @method
10915
+ * @param {number} rowIndexFrom The row index which is the beginning of the group
10916
+ * @param {number} rowIndexTo The row index which is the end of the group
10917
+ */
10918
+
10919
+
10920
+ self.groupRows = function (rowIndexFrom, rowIndexTo) {
10921
+ if (!Number.isInteger(rowIndexFrom) || rowIndexFrom < 0) throw new Error("No such row for the beginning of the group");
10922
+ var dataLength = self.viewData.length;
10923
+ if (!Number.isInteger(rowIndexFrom) || rowIndexTo <= rowIndexFrom || rowIndexTo >= dataLength) throw new Error("No such row for the end of the group");
10924
+ var ev = {
10925
+ group: {
10926
+ type: 'rows',
10927
+ from: rowIndexFrom,
10928
+ to: rowIndexTo
10929
+ }
10930
+ };
10931
+
10932
+ try {
10933
+ addGroup('rows', rowIndexFrom, rowIndexTo);
10934
+ } catch (error) {
10935
+ ev.error = error;
10936
+ }
10937
+
10938
+ self.dispatchEvent('aftercreategroup', ev);
10939
+ };
10940
+ /**
10941
+ * Remove grouping columns
10942
+ * @memberof canvasDatagrid
10943
+ * @name removeGroupColumns
10944
+ * @method
10945
+ * @param {number|string} firstColumnName Name of the first column to be grouped.
10946
+ * @param {number|string} lastColumnName Name of the last column to be grouped.
10947
+ */
10948
+
10949
+
10950
+ self.removeGroupColumns = function (firstColumnName, lastColumnName) {
10951
+ /** @type {Array<{name:string,columnIndex:number}>} */
10952
+ var schema = self.getSchema();
10953
+ var firstOne, lastOne;
10954
+
10955
+ for (var i = 0; i < schema.length; i++) {
10956
+ var it = schema[i];
10957
+ if (firstOne && lastOne) break;
10958
+
10959
+ if (it.name === firstColumnName) {
10960
+ firstOne = it;
10961
+ continue;
10962
+ }
10963
+
10964
+ if (it.name === lastColumnName) {
10965
+ lastOne = it;
10966
+ continue;
10967
+ }
10968
+ }
10969
+
10970
+ if (!firstOne) throw new Error("No such column name for first column");
10971
+ if (!lastOne) throw new Error("No such column name for last column");
10972
+ var from = firstOne.columnIndex;
10973
+ var to = lastOne.columnIndex;
10974
+ removeGroup(self.groupedColumns, from, to);
10975
+ };
10976
+ /**
10977
+ * Remove grouping columns
10978
+ * @memberof canvasDatagrid
10979
+ * @name removeGroupRows
10980
+ * @method
10981
+ * @param {number} rowIndexFrom The row index which is the beginning of the group
10982
+ * @param {number} rowIndexTo The row index which is the end of the group
10983
+ */
10984
+
10985
+
10986
+ self.removeGroupRows = function (rowIndexFrom, rowIndexTo) {
10987
+ removeGroup(self.groupedRows, rowIndexFrom, rowIndexTo);
10988
+ };
10989
+ /**
10990
+ * Toggle(expand/collapsed) grouping columns
10991
+ * @memberof canvasDatagrid
10992
+ * @name toggleGroupColumns
10993
+ * @method
10994
+ * @param {number|string} firstColumnName Name of the first column to be grouped.
10995
+ * @param {number|string} lastColumnName Name of the last column to be grouped.
10996
+ */
10997
+
10998
+
10999
+ self.toggleGroupColumns = function (firstColumnName, lastColumnName) {
11000
+ /** @type {Array<{name:string,columnIndex:number}>} */
11001
+ var schema = self.getSchema();
11002
+ var firstOne, lastOne;
11003
+
11004
+ for (var i = 0; i < schema.length; i++) {
11005
+ var it = schema[i];
11006
+ if (firstOne && lastOne) break;
11007
+
11008
+ if (it.name === firstColumnName) {
11009
+ firstOne = it;
11010
+ continue;
11011
+ }
11012
+
11013
+ if (it.name === lastColumnName) {
11014
+ lastOne = it;
11015
+ continue;
11016
+ }
11017
+ }
11018
+
11019
+ if (!firstOne || !lastOne) return;
11020
+ var from = firstOne.columnIndex;
11021
+ var to = lastOne.columnIndex;
11022
+
11023
+ if (self.toggleGroup({
11024
+ type: 'c',
11025
+ from: from,
11026
+ to: to
11027
+ })) {
11028
+ self.disposeContextMenu();
11029
+ self.setStorageData();
11030
+ self.refresh();
11031
+ }
11032
+ };
11033
+ /**
11034
+ * Toggle(expand/collapsed) grouping rows
11035
+ * @memberof canvasDatagrid
11036
+ * @name toggleGroupRows
11037
+ * @method
11038
+ * @param {number} rowIndexFrom The row index which is the beginning of the group
11039
+ * @param {number} rowIndexTo The row index which is the end of the group
11040
+ */
11041
+
11042
+
11043
+ self.toggleGroupRows = function (rowIndexFrom, rowIndexTo) {
11044
+ if (self.toggleGroup({
11045
+ type: 'r',
11046
+ from: rowIndexFrom,
11047
+ to: rowIndexTo
11048
+ })) {
11049
+ self.disposeContextMenu();
11050
+ self.setStorageData();
11051
+ self.refresh();
11052
+ }
11053
+ };
9005
11054
 
9006
11055
  self.isInGrid = function (e) {
9007
11056
  if (e.x < 0 || e.x > self.width || e.y < 0 || e.y > self.height) {
@@ -9092,6 +11141,10 @@ __webpack_require__.r(__webpack_exports__);
9092
11141
  } // TODO:
9093
11142
 
9094
11143
 
11144
+ if (!self.data) {
11145
+ self.data = {};
11146
+ }
11147
+
9095
11148
  if (!self.data[rowIndex]) {
9096
11149
  self.data[rowIndex] = {};
9097
11150
  } // TODO:
@@ -9130,6 +11183,64 @@ __webpack_require__.r(__webpack_exports__);
9130
11183
  });
9131
11184
  });
9132
11185
  };
11186
+ /**
11187
+ * Get the column group info given column belongs to
11188
+ * @memberof canvasDatagrid
11189
+ * @name getGroupsColumnBelongsTo
11190
+ * @method
11191
+ * @param {number} columnIndex Column index.
11192
+ * @returns {Array<{from:number,to:number,collapsed:boolean}>}
11193
+ */
11194
+
11195
+
11196
+ self.getGroupsColumnBelongsTo = function (columnIndex) {
11197
+ if (!self.attributes.allowGroupingColumns) return [];
11198
+ var result = [];
11199
+
11200
+ for (var i = 0; i < self.groupedColumns.length; i++) {
11201
+ var groups = self.groupedColumns[i];
11202
+
11203
+ for (var j = 0; j < groups.length; j++) {
11204
+ var group = groups[j];
11205
+
11206
+ if (columnIndex >= group.from && columnIndex <= group.to) {
11207
+ result.push(group);
11208
+ break;
11209
+ }
11210
+ }
11211
+ }
11212
+
11213
+ return result;
11214
+ };
11215
+ /**
11216
+ * Get the row group info given row belongs to
11217
+ * @memberof canvasDatagrid
11218
+ * @name getGroupsRowBelongsTo
11219
+ * @method
11220
+ * @param {number} rowIndex Row index.
11221
+ * @returns {Array<{from:number,to:number,collapsed:boolean}>}
11222
+ */
11223
+
11224
+
11225
+ self.getGroupsRowBelongsTo = function (rowIndex) {
11226
+ if (!self.attributes.allowGroupingRows) return [];
11227
+ var result = [];
11228
+
11229
+ for (var i = 0; i < self.groupedRows.length; i++) {
11230
+ var groups = self.groupedRows[i];
11231
+
11232
+ for (var j = 0; j < groups.length; j++) {
11233
+ var group = groups[j];
11234
+
11235
+ if (rowIndex >= group.from && rowIndex <= group.to) {
11236
+ result.push(group);
11237
+ break;
11238
+ }
11239
+ }
11240
+ }
11241
+
11242
+ return result;
11243
+ };
9133
11244
  /**
9134
11245
  * Checks if a given column is visible.
9135
11246
  * @memberof canvasDatagrid
@@ -9176,6 +11287,50 @@ __webpack_require__.r(__webpack_exports__);
9176
11287
  return c.columnIndex === x && c.rowIndex === y;
9177
11288
  })[0];
9178
11289
  };
11290
+ /**
11291
+ * Get a column group at grid pixel coordinate x and y.
11292
+ * @memberof canvasDatagrid
11293
+ * @name getColumnGroupAt
11294
+ * @method
11295
+ * @param {number} x Number of pixels from the left.
11296
+ * @param {number} y Number of pixels from the top.
11297
+ */
11298
+
11299
+
11300
+ self.getColumnGroupAt = function (x, y) {
11301
+ var groups = self.groupedColumns.length;
11302
+ if (groups <= 0) return;
11303
+ var yZero = self.getColumnGroupAreaHeight();
11304
+ if (y >= yZero) return;
11305
+
11306
+ for (var i = 0; i < self.visibleGroups.length; i++) {
11307
+ var g = self.visibleGroups[i];
11308
+ if (g.type !== 'c') continue;
11309
+ if (x >= g.x && y >= g.y && x <= g.x2 && y <= g.y2) return g;
11310
+ }
11311
+ };
11312
+ /**
11313
+ * Get a row group at grid pixel coordinate x and y.
11314
+ * @memberof canvasDatagrid
11315
+ * @name getRowGroupAt
11316
+ * @method
11317
+ * @param {number} x Number of pixels from the left.
11318
+ * @param {number} y Number of pixels from the top.
11319
+ */
11320
+
11321
+
11322
+ self.getRowGroupAt = function (x, y) {
11323
+ var groups = self.groupedRows.length;
11324
+ if (groups <= 0) return;
11325
+ var xZero = self.getRowGroupAreaWidth();
11326
+ if (x >= xZero) return;
11327
+
11328
+ for (var i = 0; i < self.visibleGroups.length; i++) {
11329
+ var g = self.visibleGroups[i];
11330
+ if (g.type !== 'r') continue;
11331
+ if (x >= g.x && y >= g.y && x <= g.x2 && y <= g.y2) return g;
11332
+ }
11333
+ };
9179
11334
  /**
9180
11335
  * 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.
9181
11336
  * @memberof canvasDatagrid
@@ -9210,6 +11365,8 @@ __webpack_require__.r(__webpack_exports__);
9210
11365
  return;
9211
11366
  }
9212
11367
 
11368
+ x -= self.getRowGroupAreaWidth();
11369
+ y -= self.getColumnGroupAreaHeight();
9213
11370
  var border,
9214
11371
  tsz = useTouchScrollZones ? self.attributes.touchScrollZone : 0,
9215
11372
  moveMode = self.attributes.borderDragBehavior === 'move',
@@ -9340,8 +11497,14 @@ __webpack_require__.r(__webpack_exports__);
9340
11497
  }
9341
11498
 
9342
11499
  if (cell.style === 'columnHeaderCell') {
9343
- cell.context = 'cell';
9344
- cell.dragContext = 'column-reorder';
11500
+ if (cell.x + cell.width - self.attributes.columnGrabZoneSize - self.style.cellBorderWidth > x || !self.attributes.allowRowReordering) {
11501
+ cell.dragContext = 'cell';
11502
+ cell.context = 'cell';
11503
+ } else {
11504
+ cell.context = self.cursorGrab;
11505
+ cell.dragContext = 'column-reorder';
11506
+ }
11507
+
9345
11508
  return cell;
9346
11509
  }
9347
11510