canvas-datagrid 0.3.23 → 0.4.1

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];
@@ -4535,13 +5491,26 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4535
5491
  self.hovers = {
4536
5492
  rowIndex: cell.rowIndex,
4537
5493
  columnIndex: cell.columnIndex,
4538
- onFilterButton: false
5494
+ onFilterButton: false,
5495
+ onCellTreeIcon: false
4539
5496
  };
4540
5497
 
4541
5498
  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
5499
  self.hovers.onFilterButton = true;
4543
5500
  self.draw();
4544
5501
  }
5502
+
5503
+ if (cell.isRowTree || cell.isColumnTree) {
5504
+ var pc = cell.isRowTree ? self.cellTree.rows[cell.rowIndex].parentCount : 0;
5505
+ var rc = self.style.cellTreeIconWidth * self.scale,
5506
+ rx = cell.x + cell.paddingLeft + self.canvasOffsetLeft + self.style.cellTreeIconMarginLeft + pc * (rc + cell.paddingLeft),
5507
+ ry = cell.y + self.canvasOffsetTop + self.style.cellTreeIconMarginTop * self.scale;
5508
+
5509
+ if (x >= rx && x <= rx + rc && y >= ry && y < ry + rc) {
5510
+ self.hovers.onCellTreeIcon = true;
5511
+ self.draw();
5512
+ }
5513
+ }
4545
5514
  }
4546
5515
 
4547
5516
  if (self.selecting || self.reorderObject) {
@@ -4570,6 +5539,16 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4570
5539
  dragBounds.right = s.length - 1;
4571
5540
  dragBounds.top = Math.min(sBounds.top, cell.rowIndex);
4572
5541
  dragBounds.bottom = Math.max(sBounds.bottom, cell.rowIndex);
5542
+ if (dragBounds.top < 0) dragBounds.top = 0;
5543
+ }
5544
+
5545
+ if (self.dragStartObject.rowIndex === -1) {
5546
+ sBounds = self.getSelectionBounds();
5547
+ dragBounds.left = cell.columnIndex === undefined ? sBounds.left : Math.min(sBounds.left, cell.columnIndex);
5548
+ dragBounds.right = cell.columnIndex === undefined ? sBounds.right : Math.max(sBounds.right, cell.columnIndex);
5549
+ dragBounds.top = -1;
5550
+ dragBounds.bottom = self.viewData.length - 1;
5551
+ if (dragBounds.left < 0) dragBounds.left = 0;
4573
5552
  }
4574
5553
 
4575
5554
  if (self.dragStartObject.rowIndex !== cell.rowIndex || self.dragStartObject.columnIndex !== cell.columnIndex) {
@@ -4577,8 +5556,22 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4577
5556
  }
4578
5557
 
4579
5558
  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);
5559
+ if (cell.rowIndex !== undefined && (self.attributes.selectionMode === 'row' || self.dragStartObject.columnIndex === -1) && self.rowBoundaryCrossed) {
5560
+ if (self.dragStartObject.rowIndex < cell.rowIndex) {
5561
+ dragBounds.top = self.dragStartObject.rowIndex;
5562
+ dragBounds.bottom = cell.rowIndex;
5563
+ } else {
5564
+ dragBounds.top = cell.rowIndex;
5565
+ dragBounds.bottom = self.dragStartObject.rowIndex;
5566
+ }
5567
+ } else if (cell.rowIndex !== undefined && (self.attributes.selectionMode === 'column' || self.dragStartObject.rowIndex === -1) && self.columnBoundaryCrossed) {
5568
+ if (self.dragStartObject.columnIndex < cell.columnIndex) {
5569
+ dragBounds.left = self.dragStartObject.columnIndex;
5570
+ dragBounds.right = cell.columnIndex;
5571
+ } else {
5572
+ dragBounds.left = cell.columnIndex;
5573
+ dragBounds.right = self.dragStartObject.columnIndex;
5574
+ }
4582
5575
  } else if (self.attributes.selectionMode !== 'row') {
4583
5576
  if (cell.hovered && self.hovers.onFilterButton) {
4584
5577
  if (cell.openedFilter) {
@@ -4602,12 +5595,16 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4602
5595
 
4603
5596
  self.draw();
4604
5597
  return;
5598
+ } else if (cell.hovered && self.hovers.onCellTreeIcon && e.type == 'mousedown') {
5599
+ self.toggleCollapseTree(cell.rowIndex, cell.columnIndex);
5600
+ return;
4605
5601
  } else {
4606
5602
  self.selectedFilterButton = {
4607
5603
  columnIndex: -1,
4608
5604
  rowIndex: -1
4609
5605
  };
4610
5606
  if (self.hovers.onFilterButton) return;
5607
+ if (self.hovers.onCellTreeIcon) return;
4611
5608
 
4612
5609
  if (!self.dragAddToSelection && cell.rowIndex !== undefined) {
4613
5610
  if (self.selections[cell.rowIndex] && self.selections[cell.rowIndex].indexOf(cell.columnIndex) !== -1) {
@@ -4662,6 +5659,10 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4662
5659
  }
4663
5660
  }
4664
5661
 
5662
+ var columnGroup = self.getColumnGroupAt(self.mouse.x, self.mouse.y);
5663
+ if (columnGroup) self.cursor = 'pointer';
5664
+ var rowGroup = self.getRowGroupAt(self.mouse.x, self.mouse.y);
5665
+ if (rowGroup) self.cursor = 'pointer';
4665
5666
  self.cellBoundaryCrossed = false;
4666
5667
  self.rowBoundaryCrossed = false;
4667
5668
  self.columnBoundaryCrossed = false;
@@ -4718,10 +5719,26 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4718
5719
  return;
4719
5720
  }
4720
5721
 
5722
+ var group = self.getColumnGroupAt(pos.x, pos.y);
5723
+ if (!group) group = self.getRowGroupAt(pos.x, pos.y);
5724
+
5725
+ if (group) {
5726
+ if (self.toggleGroup(group)) {
5727
+ self.setStorageData();
5728
+ self.refresh();
5729
+ return;
5730
+ }
5731
+ }
5732
+
4721
5733
  if (!self.hasFocus) {
4722
5734
  return;
4723
5735
  }
4724
5736
 
5737
+ var leftOffset = self.getRowGroupAreaWidth();
5738
+ var topOffset = self.getColumnGroupAreaHeight();
5739
+ var xInGrid = pos.x - leftOffset;
5740
+ var yInGrid = pos.y - topOffset;
5741
+
4725
5742
  if (['rowHeaderCell', 'columnHeaderCell'].indexOf(self.currentCell.style) === -1 && !ctrl) {
4726
5743
  if (!self.hovers.onFilterButton) {
4727
5744
  self.setActiveCell(i.columnIndex, i.rowIndex);
@@ -4753,7 +5770,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4753
5770
  self.selections[i.rowIndex] = self.selections[i.rowIndex] || [];
4754
5771
 
4755
5772
  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) {
5773
+ 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
5774
  self.toggleTree(i.rowIndex);
4758
5775
  return;
4759
5776
  }
@@ -4793,7 +5810,6 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4793
5810
 
4794
5811
  if (self.scrollBox.scrollLeft > self.scrollBox.scrollWidth - self.attributes.resizeScrollZone && self.dragMode === 'ew-resize') {
4795
5812
  self.resize(true);
4796
- self.scrollBox.scrollLeft += x;
4797
5813
  }
4798
5814
 
4799
5815
  if (self.dragMode === 'ew-resize') {
@@ -4959,6 +5975,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4959
5975
  if (Math.abs(x) > self.attributes.reorderDeadZone || Math.abs(y) > self.attributes.reorderDeadZone) {
4960
5976
  self.reorderObject = self.draggingItem;
4961
5977
  if (self.isMultiRowsSelected) self.reorderObject = self.getVisibleCellByIndex(-1, self.activeCell.rowIndex);
5978
+ if (!self.reorderObject) return;
4962
5979
  self.reorderTarget = self.currentCell;
4963
5980
  self.reorderObject.dragOffset = {
4964
5981
  x: x,
@@ -5105,6 +6122,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
5105
6122
  rowHeaderCellWidth = self.getRowHeaderCellWidth();
5106
6123
  self.ignoreNextClick = true;
5107
6124
  self.freezeMarkerPosition = pos;
6125
+ pos.x -= self.getRowGroupAreaWidth();
6126
+ pos.y -= self.getColumnGroupAreaHeight();
5108
6127
 
5109
6128
  if (self.currentCell && self.currentCell.rowIndex !== undefined && self.dragMode === 'frozen-row-marker') {
5110
6129
  self.scrollBox.scrollTop = 0;
@@ -5219,6 +6238,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
5219
6238
 
5220
6239
  if ((self.attributes.selectionMode === 'row' || self.dragStartObject.columnIndex === -1) && self.dragStartObject.rowIndex > -1) {
5221
6240
  self.selectRow(self.dragStartObject.rowIndex, ctrl, null);
6241
+ } else if ((self.attributes.selectionMode === 'column' || self.dragStartObject.rowIndex === -1) && self.dragStartObject.columnIndex > -1) {
6242
+ self.selectColumn(self.currentCell.header.index, ctrl, e.shiftKey);
5222
6243
  } else if (self.attributes.selectionMode !== 'row') {
5223
6244
  self.mousemove(e);
5224
6245
  }
@@ -5603,8 +6624,13 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
5603
6624
  }
5604
6625
  } else if (self.currentCell.context === 'ew-resize' && self.currentCell.style === 'cornerCell') {
5605
6626
  self.autosize();
5606
- } else if (['cell', 'activeCell'].includes(self.currentCell.style) && !self.hovers.onFilterButton) {
5607
- self.beginEditAt(self.currentCell.columnIndex, self.currentCell.rowIndex);
6627
+ } else if (['cell', 'activeCell'].includes(self.currentCell.style) && !self.hovers.onFilterButton && !self.hovers.onCellTreeIcon) {
6628
+ if (self.currentCell.isRowTree || self.currentCell.isColumnTree) {
6629
+ self.cellTreeExpandCollapse(self.currentCell.rowIndex, self.currentCell.columnIndex);
6630
+ self.draw();
6631
+ } else {
6632
+ self.beginEditAt(self.currentCell.columnIndex, self.currentCell.rowIndex);
6633
+ }
5608
6634
  }
5609
6635
  };
5610
6636
 
@@ -5809,19 +6835,19 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
5809
6835
  });
5810
6836
  };
5811
6837
 
5812
- self.cut = function (e) {
6838
+ self.cut = function (event) {
5813
6839
  if (self.dispatchEvent('cut', {
5814
- NativeEvent: e
6840
+ NativeEvent: event
5815
6841
  })) {
5816
6842
  return;
5817
6843
  } // Expecting instance of `ClipboardEvent` with `clipboardData` attribute
5818
6844
 
5819
6845
 
5820
- if (!self.hasFocus || !e.clipboardData) {
6846
+ if (!self.hasFocus || !event.clipboardData) {
5821
6847
  return;
5822
6848
  }
5823
6849
 
5824
- self.copySelectedCellsToClipboard(e.clipboardData);
6850
+ self.copySelectedCellsToClipboard(event.clipboardData);
5825
6851
  var affectedCells = self.clearSelectedCells();
5826
6852
  self.dispatchEvent('aftercut', {
5827
6853
  cells: affectedCells
@@ -5829,22 +6855,23 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
5829
6855
  requestAnimationFrame(function () {
5830
6856
  return self.draw();
5831
6857
  });
6858
+ event.preventDefault();
5832
6859
  };
5833
6860
 
5834
- self.copy = function (e) {
6861
+ self.copy = function (event) {
5835
6862
  if (self.dispatchEvent('copy', {
5836
- NativeEvent: e
6863
+ NativeEvent: event
5837
6864
  })) {
5838
6865
  return;
5839
6866
  } // Expecting instance of `ClipboardEvent` with `clipboardData` attribute
5840
6867
 
5841
6868
 
5842
- if (!self.hasFocus || !e.clipboardData) {
6869
+ if (!self.hasFocus || !event.clipboardData) {
5843
6870
  return;
5844
6871
  }
5845
6872
 
5846
- self.copySelectedCellsToClipboard(e.clipboardData);
5847
- e.preventDefault();
6873
+ self.copySelectedCellsToClipboard(event.clipboardData);
6874
+ event.preventDefault();
5848
6875
  };
5849
6876
 
5850
6877
  return;
@@ -6005,7 +7032,7 @@ var parseData = function parseData(data, mimeType) {
6005
7032
  };
6006
7033
 
6007
7034
  var htmlSafe = function htmlSafe(value) {
6008
- if (typeof value === 'number') return value;
7035
+ if (typeof value !== 'string') return value;
6009
7036
  return value.replace(/</g, '&lt;').replace(/>/g, '&gt;');
6010
7037
  };
6011
7038
 
@@ -6027,7 +7054,7 @@ var createHTMLString = function createHTMLString(selectedData, isNeat) {
6027
7054
  var htmlString = '<table>';
6028
7055
  htmlString += selectedData.map(function (row) {
6029
7056
  return '<tr>' + Object.values(row).map(function (value) {
6030
- return '<td>' + htmlSafe(value) + '</td>';
7057
+ return ['<td>', htmlSafe(value), '</td>'].join('');
6031
7058
  }).join('') + '</tr>';
6032
7059
  }).join('');
6033
7060
  htmlString += '</table>';
@@ -6059,6 +7086,14 @@ __webpack_require__.r(__webpack_exports__);
6059
7086
  /*globals HTMLElement: false, Reflect: false, define: true, MutationObserver: false, requestAnimationFrame: false, performance: false, btoa: false*/
6060
7087
 
6061
7088
 
7089
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
7090
+
7091
+ 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."); }
7092
+
7093
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
7094
+
7095
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
7096
+
6062
7097
  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); }
6063
7098
 
6064
7099
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
@@ -6129,6 +7164,21 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6129
7164
  self.scrollBox = {};
6130
7165
  self.visibleRows = [];
6131
7166
  self.visibleCells = [];
7167
+ /**
7168
+ * This array stored all groups information with context for drawing,
7169
+ * it is generated by drawing functions,
7170
+ * and be used for searching groups when users operate on the spreadsheet
7171
+ * Each item of this array contains these properties:
7172
+ * - `type`: its available values: 'c' and 'r'. indicates the type of this item, 'c' for column group
7173
+ * and 'r' for row group.
7174
+ * - `x`,`y`: the left-top point of this group's rendering area.
7175
+ * - `x2`, `y2`: the right-bottom of this group's rendering area.
7176
+ * - `collapsed`: this value indicates the collapsed status of this group.
7177
+ * - `from`, `to`: The column index range of this group (We use this value for searching the group)
7178
+ * - `row`: The row index for column groups (We use this value for searching the group)
7179
+ */
7180
+
7181
+ self.visibleGroups = [];
6132
7182
  self.sizes = {
6133
7183
  rows: {},
6134
7184
  columns: {},
@@ -6143,6 +7193,18 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6143
7193
  columnIndex: -1,
6144
7194
  rowIndex: -1
6145
7195
  };
7196
+ self.cellTree = {
7197
+ rows: [],
7198
+ columns: {},
7199
+ tempSchema: {},
7200
+ rowTreeColIndex: 0,
7201
+ columnTreeRowStartIndex: 0,
7202
+ columnTreeRowEndIndex: 0,
7203
+ origin: {
7204
+ rows: [],
7205
+ columns: {}
7206
+ }
7207
+ };
6146
7208
  self.hovers = {};
6147
7209
  self.attributes = {};
6148
7210
  self.style = {};
@@ -6158,9 +7220,31 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6158
7220
  self.scrollPixelLeft = 0;
6159
7221
  self.childGrids = {};
6160
7222
  self.openChildren = {};
7223
+ /**
7224
+ * Array for grouped columns
7225
+ * Each item in this array is an array and it represents some grouping in one row
7226
+ * A grouping descriptor has three properties:
7227
+ * - `from`: The column index of the first column
7228
+ * - `to`: The column index of the last column
7229
+ * - `collapsed`: Is this group be collapsed
7230
+ * @example [[{ from: 1, to: 2, collapsed: false }]]
7231
+ */
7232
+
7233
+ self.groupedColumns = [];
7234
+ /**
7235
+ * Array for grouped rows
7236
+ * Each item in this array is an array and it represents some grouping in one column
7237
+ * A grouping descriptor has three properties:
7238
+ * - `from`: The row index of the first row
7239
+ * - `to`: The row index of the last row
7240
+ * - `collapsed`: Is this group be collapsed
7241
+ * @example [[{ from: 1, to: 2, collapsed: false }]]
7242
+ */
7243
+
7244
+ self.groupedRows = [];
6161
7245
  self.scrollModes = ['vertical-scroll-box', 'vertical-scroll-top', 'vertical-scroll-bottom', 'horizontal-scroll-box', 'horizontal-scroll-right', 'horizontal-scroll-left'];
6162
7246
  self.componentL1Events = {};
6163
- 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'];
7247
+ 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'];
6164
7248
  self.mouse = {
6165
7249
  x: 0,
6166
7250
  y: 0
@@ -6407,6 +7491,166 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6407
7491
  self.getBoundColumnIndexFromViewColumnIndex = function (viewColumnIndex) {
6408
7492
  return self.orders.columns[viewColumnIndex];
6409
7493
  };
7494
+ /**
7495
+ * Get the height of the area about column groups for rendering and handling events.
7496
+ */
7497
+
7498
+
7499
+ self.getColumnGroupAreaHeight = function () {
7500
+ if (!self.attributes.allowGroupingColumns) {
7501
+ return 0;
7502
+ }
7503
+
7504
+ var groups = self.groupedColumns.length;
7505
+ var base = self.style.columnGroupRowHeight * self.scale;
7506
+ return base * groups;
7507
+ };
7508
+ /**
7509
+ * Get the width of the area about row groups for rendering and handling events.
7510
+ */
7511
+
7512
+
7513
+ self.getRowGroupAreaWidth = function () {
7514
+ if (!self.attributes.allowGroupingRows) {
7515
+ return 0;
7516
+ }
7517
+
7518
+ var groups = self.groupedRows.length;
7519
+ var base = self.style.rowGroupColumnWidth * self.scale;
7520
+ return base * groups;
7521
+ };
7522
+
7523
+ self.getCollapsedColumnGroups = function () {
7524
+ var result = [];
7525
+
7526
+ for (var rowIndex = 0; rowIndex < self.groupedColumns.length; rowIndex++) {
7527
+ var groups = self.groupedColumns[rowIndex];
7528
+
7529
+ for (var groupIndex = 0; groupIndex < groups.length; groupIndex++) {
7530
+ var group = groups[groupIndex];
7531
+ if (group.collapsed) result.push(group);
7532
+ }
7533
+ }
7534
+
7535
+ return result;
7536
+ };
7537
+
7538
+ self.getCollapsedRowGroups = function () {
7539
+ var result = [];
7540
+
7541
+ for (var rowIndex = 0; rowIndex < self.groupedRows.length; rowIndex++) {
7542
+ var groups = self.groupedRows[rowIndex];
7543
+
7544
+ for (var groupIndex = 0; groupIndex < groups.length; groupIndex++) {
7545
+ var group = groups[groupIndex];
7546
+ if (group.collapsed) result.push(group);
7547
+ }
7548
+ }
7549
+
7550
+ return result;
7551
+ };
7552
+ /**
7553
+ * Toggle the collapse status of a group (expanded/collapsed)
7554
+ * @param {{type:string,from:number,to:number}} group
7555
+ */
7556
+
7557
+
7558
+ self.toggleGroup = function (group) {
7559
+ if (group.type === 'c') {
7560
+ var from = group.from,
7561
+ to = group.to;
7562
+ /** @type {{from:number,to:number,collapsed:boolean}} */
7563
+
7564
+ var matchedGroup;
7565
+ /** @type {Array<Array<{from:number,to:number,collapsed:boolean}>>} */
7566
+
7567
+ var allGroups = self.groupedColumns;
7568
+
7569
+ for (var i = 0; i < allGroups.length; i++) {
7570
+ var groups = allGroups[i];
7571
+
7572
+ for (var gi = 0; gi < groups.length; gi++) {
7573
+ var _group = groups[gi];
7574
+
7575
+ if (_group.from === from && _group.to === to) {
7576
+ matchedGroup = _group;
7577
+ break;
7578
+ }
7579
+ }
7580
+
7581
+ if (matchedGroup) break;
7582
+ }
7583
+
7584
+ if (!matchedGroup) return;
7585
+ var nextCollapsed = !matchedGroup.collapsed;
7586
+ matchedGroup.collapsed = nextCollapsed;
7587
+ return true;
7588
+ }
7589
+
7590
+ if (group.type === 'r') {
7591
+ var _from = group.from,
7592
+ _to = group.to;
7593
+ /** @type {{from:number,to:number,collapsed:boolean}} */
7594
+
7595
+ var _matchedGroup;
7596
+ /** @type {Array<Array<{from:number,to:number,collapsed:boolean}>>} */
7597
+
7598
+
7599
+ var _allGroups = self.groupedRows;
7600
+
7601
+ for (var _i3 = 0; _i3 < _allGroups.length; _i3++) {
7602
+ var _groups = _allGroups[_i3];
7603
+
7604
+ for (var _gi = 0; _gi < _groups.length; _gi++) {
7605
+ var _group2 = _groups[_gi];
7606
+
7607
+ if (_group2.from === _from && _group2.to === _to) {
7608
+ _matchedGroup = _group2;
7609
+ break;
7610
+ }
7611
+ }
7612
+
7613
+ if (_matchedGroup) break;
7614
+ }
7615
+
7616
+ if (!_matchedGroup) return;
7617
+
7618
+ var _nextCollapsed = !_matchedGroup.collapsed;
7619
+
7620
+ _matchedGroup.collapsed = _nextCollapsed;
7621
+ return true;
7622
+ }
7623
+
7624
+ return false;
7625
+ };
7626
+
7627
+ self.isNewGroupRangeValid = function (groupsArray, from, to) {
7628
+ for (var i = 0; i < groupsArray.length; i++) {
7629
+ var groups = groupsArray[i];
7630
+
7631
+ for (var gIndex = 0; gIndex < groups.length; gIndex++) {
7632
+ var group = groups[gIndex];
7633
+ if (from === group.to + 1) return false;
7634
+ if (from > group.to) continue;
7635
+
7636
+ if (from === group.from) {
7637
+ if (to === group.to) return false;
7638
+ if (to > group.to) return true;
7639
+ break; // check smaller range
7640
+ }
7641
+
7642
+ if (from > group.from) {
7643
+ if (to > group.to) return false;
7644
+ break; // check smaller range
7645
+ }
7646
+
7647
+ if (to < group.to) return false;
7648
+ return true;
7649
+ }
7650
+ }
7651
+
7652
+ return true;
7653
+ };
6410
7654
 
6411
7655
  self.getColumnHeaderCellHeight = function () {
6412
7656
  if (!self.attributes.showColumnHeaders) {
@@ -6559,6 +7803,19 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6559
7803
  return self.columnFilters && Object.keys(self.columnFilters).length > 0;
6560
7804
  };
6561
7805
 
7806
+ self.hasCollapsedRowGroup = function () {
7807
+ for (var i = 0; i < self.groupedRows.length; i++) {
7808
+ var groups = self.groupedRows[i];
7809
+
7810
+ for (var j = 0; j < groups.length; j++) {
7811
+ var g = groups[j];
7812
+ if (g.collapsed) return true;
7813
+ }
7814
+ }
7815
+
7816
+ return false;
7817
+ };
7818
+
6562
7819
  self.getFilteredAndSortedViewData = function (originalData) {
6563
7820
  // We make a copy of originalData here in order be able to
6564
7821
  // filter and sort rows without modifying the original array.
@@ -6571,7 +7828,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6571
7828
  }); // Apply filtering
6572
7829
 
6573
7830
  var _loop = function _loop() {
6574
- var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i3], 2),
7831
+ var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i4], 2),
6575
7832
  headerName = _Object$entries2$_i[0],
6576
7833
  filterText = _Object$entries2$_i[1];
6577
7834
 
@@ -6592,11 +7849,81 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6592
7849
  });
6593
7850
  };
6594
7851
 
6595
- for (var _i3 = 0, _Object$entries2 = Object.entries(self.columnFilters); _i3 < _Object$entries2.length; _i3++) {
7852
+ for (var _i4 = 0, _Object$entries2 = Object.entries(self.columnFilters); _i4 < _Object$entries2.length; _i4++) {
6596
7853
  var _ret = _loop();
6597
7854
 
6598
7855
  if (_ret === "continue") continue;
6599
- } // Apply sorting
7856
+ } //#region Hide rows from collapsed group
7857
+
7858
+ /** @type {number[][]} */
7859
+
7860
+
7861
+ var collapsedGroups = [];
7862
+
7863
+ for (var i = 0; i < self.groupedRows.length; i++) {
7864
+ var rows = self.groupedRows[i];
7865
+
7866
+ for (var j = 0; j < rows.length; j++) {
7867
+ var r = rows[j];
7868
+ if (!r.collapsed) continue;
7869
+ collapsedGroups.push([r.from, r.to]);
7870
+ }
7871
+ }
7872
+
7873
+ if (collapsedGroups.length > 0) {
7874
+ //#region merge groups
7875
+ collapsedGroups.sort(function (a, b) {
7876
+ return a[0] - b[0];
7877
+ });
7878
+ var newLen = 0;
7879
+ var len = collapsedGroups.length;
7880
+
7881
+ for (var _i5 = 0; _i5 < len; _i5++) {
7882
+ var _r = collapsedGroups[_i5];
7883
+
7884
+ if (_i5 === len - 1) {
7885
+ collapsedGroups[newLen++] = _r;
7886
+ break;
7887
+ }
7888
+
7889
+ var to = _r[1];
7890
+
7891
+ var _collapsedGroups = _slicedToArray(collapsedGroups[_i5 + 1], 2),
7892
+ from2 = _collapsedGroups[0],
7893
+ to2 = _collapsedGroups[1];
7894
+
7895
+ if (from2 > to + 1) {
7896
+ collapsedGroups[newLen++] = _r;
7897
+ continue;
7898
+ }
7899
+
7900
+ collapsedGroups[_i5 + 1] = _r;
7901
+ if (to2 > to) collapsedGroups[_i5 + 1][1] = to2;
7902
+ }
7903
+
7904
+ collapsedGroups = collapsedGroups.slice(0, newLen); //#endregion merge groups
7905
+ //#region omit rows by groups
7906
+
7907
+ var g = collapsedGroups.shift();
7908
+
7909
+ for (var start = 0; start < newViewData.length; start++) {
7910
+ var it = newViewData[start][1];
7911
+ if (it < g[0]) continue;
7912
+ var end = start + 1;
7913
+
7914
+ for (; end < newViewData.length; end++) {
7915
+ var it2 = newViewData[end][1];
7916
+ if (it2 > g[1]) break;
7917
+ }
7918
+
7919
+ newViewData.splice(start, end - start);
7920
+ g = collapsedGroups.shift();
7921
+ if (!g) break;
7922
+ start--;
7923
+ } //#endregion omit rows by groups
7924
+
7925
+ } //#endregion Hide rows from collapsed group
7926
+ // Apply sorting
6600
7927
 
6601
7928
 
6602
7929
  var _iterator8 = _createForOfIteratorHelper(self.orderings.columns),
@@ -6811,6 +8138,329 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6811
8138
  }
6812
8139
  };
6813
8140
 
8141
+ self.toggleCollapseTree = function (rowIndex, columnIndex, type) {
8142
+ var tempData = [];
8143
+ var collapsedCount = 0;
8144
+
8145
+ if (columnIndex == self.cellTree.rowTreeColIndex && (rowIndex > 0 || rowIndex == 0 && self.cellTree.rows[0].icon)) {
8146
+ var ctr = self.cellTree.rows;
8147
+
8148
+ switch (type) {
8149
+ case 'Expand':
8150
+ ctr[rowIndex].expand = true;
8151
+ self.cellTree.origin.rows[ctr[rowIndex].index].expand = true;
8152
+ break;
8153
+
8154
+ case 'Collapse':
8155
+ ctr[rowIndex].expand = false;
8156
+ self.cellTree.origin.rows[ctr[rowIndex].index].expand = false;
8157
+ break;
8158
+
8159
+ default:
8160
+ ctr[rowIndex].expand = !ctr[rowIndex].expand;
8161
+ self.cellTree.origin.rows[ctr[rowIndex].index].expand = ctr[rowIndex].expand;
8162
+ }
8163
+
8164
+ for (var ri = ctr[rowIndex].index + 1; ri <= ctr[rowIndex].lastchild; ri++) {
8165
+ var orTree = self.cellTree.origin.rows[ri];
8166
+
8167
+ if (ctr[rowIndex].expand) {
8168
+ orTree.hide = false;
8169
+ if (orTree.icon && !orTree.expand) ri = orTree.lastchild;
8170
+ } else {
8171
+ orTree.hide = true;
8172
+ }
8173
+ }
8174
+ } else if (self.cellTree.columns[rowIndex]) {
8175
+ var ctc = self.cellTree.columns[rowIndex];
8176
+
8177
+ switch (type) {
8178
+ case 'Expand':
8179
+ ctc[columnIndex].expand = true;
8180
+ break;
8181
+
8182
+ case 'Collapse':
8183
+ ctc[columnIndex].expand = false;
8184
+ break;
8185
+
8186
+ default:
8187
+ ctc[columnIndex].expand = !ctc[columnIndex].expand;
8188
+ }
8189
+
8190
+ for (var ci = ctc[columnIndex].index + 1; ci <= ctc[columnIndex].lastchild; ci++) {
8191
+ if (ctc[columnIndex].expand) self.cellTree.tempSchema[ci].hidden = false;else self.cellTree.tempSchema[ci].hidden = true;
8192
+ }
8193
+
8194
+ var rc = 0,
8195
+ _ri;
8196
+
8197
+ if (ctc[columnIndex].expand) {
8198
+ while (rc < ctc[columnIndex].child) {
8199
+ _ri = rowIndex + rc + 1;
8200
+
8201
+ for (var _ci = ctc[columnIndex].index; _ci <= ctc[columnIndex].lastchild; _ci++) {
8202
+ if (self.cellTree.origin.columns[_ri] && self.cellTree.origin.columns[_ri][_ci].icon && !self.cellTree.origin.columns[_ri][_ci].expand) {
8203
+ for (var si = _ci + 1; si <= self.cellTree.origin.columns[_ri][_ci].lastchild; si++) {
8204
+ self.cellTree.tempSchema[si].hidden = true;
8205
+ }
8206
+ }
8207
+ }
8208
+
8209
+ rc++;
8210
+ }
8211
+ }
8212
+ }
8213
+
8214
+ var otherData = {};
8215
+ var collapsed = [];
8216
+ self.cellTree.rows = [];
8217
+ self.cellTree.columns = {};
8218
+
8219
+ for (var k in self.cellTree.origin.rows) {
8220
+ var tempRow = [];
8221
+ var tree = self.cellTree.origin.rows[k];
8222
+
8223
+ if (!tree.hide) {
8224
+ var colTrees = [];
8225
+ var collapsedColCount = 0;
8226
+
8227
+ if (k < self.cellTree.columnTreeRowStartIndex) {
8228
+ tempData.push(self.originalData[k]);
8229
+ } else {
8230
+ if (k > self.cellTree.columnTreeRowEndIndex) {
8231
+ otherData[k] = self.viewData[k];
8232
+ collapsedCount++;
8233
+ } else {
8234
+ for (var l = 0; l < self.originalData[k].length; l++) {
8235
+ if (!self.cellTree.tempSchema[l].hidden) {
8236
+ if (l < self.cellTree.rowTreeColIndex) {
8237
+ if (!Object.prototype.hasOwnProperty.call(otherData, k)) otherData[k] = [];
8238
+ otherData[k].push(self.viewData[k][l]);
8239
+ }
8240
+
8241
+ tempRow.push(self.originalData[k][l]);
8242
+ if (Object.prototype.hasOwnProperty.call(self.cellTree.origin.columns, k)) colTrees.push(self.cellTree.origin.columns[k][l]);
8243
+ } else collapsedColCount++;
8244
+ }
8245
+
8246
+ tempRow.push.apply(tempRow, _toConsumableArray(Array(collapsedColCount).fill().map(function () {
8247
+ return '';
8248
+ })));
8249
+
8250
+ if (colTrees.length) {
8251
+ colTrees.push.apply(colTrees, _toConsumableArray(Array(collapsedColCount).fill().map(function () {
8252
+ return {};
8253
+ })));
8254
+ self.cellTree.columns[k] = colTrees;
8255
+ }
8256
+
8257
+ tempData.push(tempRow);
8258
+ }
8259
+ }
8260
+
8261
+ self.cellTree.rows.push(tree);
8262
+ } else {
8263
+ for (var _l = 0; _l < self.cellTree.rowTreeColIndex; _l++) {
8264
+ tempRow.push(self.viewData[k][_l]);
8265
+ }
8266
+
8267
+ otherData[k] = tempRow;
8268
+ collapsed.push(Array(self.viewData[0].length).fill().map(function () {
8269
+ return '';
8270
+ }));
8271
+ collapsedCount++;
8272
+ }
8273
+ }
8274
+
8275
+ if (collapsedCount) {
8276
+ var _self$cellTree$rows;
8277
+
8278
+ (_self$cellTree$rows = self.cellTree.rows).push.apply(_self$cellTree$rows, _toConsumableArray(Array(collapsedCount).fill().map(function (u, index) {
8279
+ return {
8280
+ index: self.cellTree.rows.length + index
8281
+ };
8282
+ })));
8283
+
8284
+ tempData.push.apply(tempData, collapsed);
8285
+ }
8286
+
8287
+ for (var _k in otherData) {
8288
+ if (_k > self.cellTree.columnTreeRowEndIndex) tempData[_k] = otherData[_k];else for (var _l2 in otherData[_k]) {
8289
+ tempData[_k][_l2] = otherData[_k][_l2];
8290
+ }
8291
+ }
8292
+
8293
+ self.viewData = tempData;
8294
+ };
8295
+
8296
+ self.cellTreeExpandCollapse = function (rowIndex, columnIndex, type) {
8297
+ if (columnIndex == self.cellTree.rowTreeColIndex && (rowIndex > 0 || rowIndex == 0 && self.cellTree.rows[0].icon)) {
8298
+ var ctr = self.cellTree.rows;
8299
+
8300
+ switch (type) {
8301
+ case 'Expand':
8302
+ ctr[rowIndex].expand = true;
8303
+ break;
8304
+
8305
+ case 'Collapse':
8306
+ ctr[rowIndex].expand = false;
8307
+ break;
8308
+
8309
+ default:
8310
+ ctr[rowIndex].expand = !ctr[rowIndex].expand;
8311
+ }
8312
+
8313
+ for (var ri = rowIndex + 1; ri <= ctr[rowIndex].lastchild; ri++) {
8314
+ if (ctr[rowIndex].expand) {
8315
+ ctr[ri].hide = false;
8316
+ if (ctr[ri].icon && !ctr[ri].expand) ri = ctr[ri].lastchild;
8317
+ } else {
8318
+ ctr[ri].hide = true;
8319
+ }
8320
+ }
8321
+ } else if (self.cellTree.columns[rowIndex]) {
8322
+ var ctc = self.cellTree.columns[rowIndex];
8323
+
8324
+ switch (type) {
8325
+ case 'Expand':
8326
+ ctc[columnIndex].expand = true;
8327
+ break;
8328
+
8329
+ case 'Collapse':
8330
+ ctc[columnIndex].expand = false;
8331
+ break;
8332
+
8333
+ default:
8334
+ ctc[columnIndex].expand = !ctc[columnIndex].expand;
8335
+ }
8336
+
8337
+ for (var ci = columnIndex + 1; ci <= ctc[columnIndex].lastchild; ci++) {
8338
+ if (ctc[columnIndex].expand) self.tempSchema[ci].hidden = false;else self.tempSchema[ci].hidden = true;
8339
+ }
8340
+
8341
+ var rc = 0,
8342
+ _ri2;
8343
+
8344
+ if (ctc[columnIndex].expand) {
8345
+ while (rc < ctc[columnIndex].child) {
8346
+ _ri2 = rowIndex + rc + 1;
8347
+
8348
+ for (var _ci2 = columnIndex; _ci2 <= ctc[columnIndex].lastchild; _ci2++) {
8349
+ if (self.cellTree.columns[_ri2] && self.cellTree.columns[_ri2][_ci2].icon && !self.cellTree.columns[_ri2][_ci2].expand) {
8350
+ for (var si = _ci2 + 1; si <= self.cellTree.columns[_ri2][_ci2].lastchild; si++) {
8351
+ self.tempSchema[si].hidden = true;
8352
+ }
8353
+ }
8354
+ }
8355
+
8356
+ rc++;
8357
+ }
8358
+ }
8359
+ }
8360
+ };
8361
+
8362
+ self.initCellTreeSettings = function () {
8363
+ if (self.viewData === undefined) return;
8364
+
8365
+ if (self.attributes.rowTree.length > 0 && self.viewData.length > 0) {
8366
+ self.cellTree.rows = Array(self.viewData.length).fill().map(function (u, index) {
8367
+ return {
8368
+ index: index
8369
+ };
8370
+ });
8371
+ self.cellTree.rowTreeColIndex = self.attributes.rowTreeColIndex;
8372
+ var invalidRowTree = false;
8373
+
8374
+ var _iterator9 = _createForOfIteratorHelper(self.attributes.rowTree),
8375
+ _step9;
8376
+
8377
+ try {
8378
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
8379
+ var rt = _step9.value;
8380
+
8381
+ if (self.cellTree.rows.length <= rt.end) {
8382
+ invalidRowTree = true;
8383
+ break;
8384
+ }
8385
+
8386
+ for (var ri = rt.begin; ri <= rt.end; ri++) {
8387
+ if (ri == rt.begin) {
8388
+ self.cellTree.rows[ri].icon = true;
8389
+ self.cellTree.rows[ri].lastchild = rt.end;
8390
+ self.cellTree.rows[ri].expand = true;
8391
+ if (!self.cellTree.rows[ri].parentCount) self.cellTree.rows[ri].parentCount = 0;
8392
+ } else {
8393
+ self.cellTree.rows[ri].hide = false;
8394
+ self.cellTree.rows[ri].parentIndex = rt.begin;
8395
+ if (self.cellTree.rows[ri] && self.cellTree.rows[ri].parentCount) self.cellTree.rows[ri].parentCount += 1;else self.cellTree.rows[ri].parentCount = 1;
8396
+ }
8397
+ }
8398
+ }
8399
+ } catch (err) {
8400
+ _iterator9.e(err);
8401
+ } finally {
8402
+ _iterator9.f();
8403
+ }
8404
+
8405
+ if (invalidRowTree) self.cellTree.rows = {};
8406
+ }
8407
+
8408
+ if (self.attributes.columnTree.length > 0 && self.viewData.length > 0) {
8409
+ self.cellTree.columnTreeRowStartIndex = self.attributes.columnTreeRowStartIndex;
8410
+ self.cellTree.columnTreeRowEndIndex = self.attributes.columnTreeRowEndIndex;
8411
+ var dataColumnLength = Object.keys(self.viewData[0]).length;
8412
+ var invalidColumnTree = false;
8413
+
8414
+ var _iterator10 = _createForOfIteratorHelper(self.attributes.columnTree),
8415
+ _step10;
8416
+
8417
+ try {
8418
+ for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
8419
+ var ct = _step10.value;
8420
+
8421
+ if (dataColumnLength <= ct.end) {
8422
+ invalidColumnTree = true;
8423
+ break;
8424
+ }
8425
+
8426
+ if (!self.cellTree.columns[ct.row]) self.cellTree.columns[ct.row] = Array(dataColumnLength).fill().map(function (u, index) {
8427
+ return {
8428
+ index: index
8429
+ };
8430
+ });
8431
+
8432
+ for (var i = ct.begin; i <= ct.end; i++) {
8433
+ var ctc = self.cellTree.columns[ct.row][i];
8434
+
8435
+ if (i == ct.begin) {
8436
+ ctc.icon = true;
8437
+ ctc.lastchild = ct.end;
8438
+ ctc.length = ct.end - ct.begin;
8439
+ ctc.expand = true;
8440
+ if (ct.child) ctc.child = ct.child;else ctc.child = 0;
8441
+ }
8442
+ }
8443
+ }
8444
+ } catch (err) {
8445
+ _iterator10.e(err);
8446
+ } finally {
8447
+ _iterator10.f();
8448
+ }
8449
+
8450
+ self.cellTree.tempSchema = Array(dataColumnLength).fill().map(function () {
8451
+ return {
8452
+ hidden: false
8453
+ };
8454
+ });
8455
+ if (invalidColumnTree) self.cellTree.columns = {};
8456
+ }
8457
+
8458
+ self.cellTree.origin = {
8459
+ rows: self.cellTree.rows,
8460
+ columns: self.cellTree.columns
8461
+ };
8462
+ };
8463
+
6814
8464
  self.getDomRoot = function () {
6815
8465
  return self.shadowRoot ? self.shadowRoot.host : self.parentNode;
6816
8466
  };
@@ -6991,6 +8641,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6991
8641
  self.intf.gotoCell = self.gotoCell;
6992
8642
  self.intf.gotoRow = self.gotoRow;
6993
8643
  self.intf.addButton = self.addButton;
8644
+ self.intf.toggleCellCollapseTree = self.toggleCellCollapseTree;
8645
+ self.intf.expandCollapseCellTree = self.expandCollapseCellTree;
6994
8646
  self.intf.getHeaderByName = self.getHeaderByName;
6995
8647
  self.intf.findColumnScrollLeft = self.findColumnScrollLeft;
6996
8648
  self.intf.findRowScrollTop = self.findRowScrollTop;
@@ -6998,6 +8650,14 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
6998
8650
  self.intf.findColumnMaxTextLength = self.findColumnMaxTextLength;
6999
8651
  self.intf.disposeContextMenu = self.disposeContextMenu;
7000
8652
  self.intf.getCellAt = self.getCellAt;
8653
+ self.intf.groupColumns = self.groupColumns;
8654
+ self.intf.groupRows = self.groupRows;
8655
+ self.intf.removeGroupColumns = self.removeGroupColumns;
8656
+ self.intf.removeGroupRows = self.removeGroupRows;
8657
+ self.intf.toggleGroupColumns = self.toggleGroupColumns;
8658
+ self.intf.toggleGroupRows = self.toggleGroupRows;
8659
+ self.intf.getGroupsColumnBelongsTo = self.getGroupsColumnBelongsTo;
8660
+ self.intf.getGroupsRowBelongsTo = self.getGroupsRowBelongsTo;
7001
8661
  self.intf.isCellVisible = self.isCellVisible;
7002
8662
  self.intf.isRowVisible = self.isRowVisible;
7003
8663
  self.intf.isColumnVisible = self.isColumnVisible;
@@ -7128,6 +8788,10 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
7128
8788
  self.tryLoadStoredSettings();
7129
8789
  }
7130
8790
 
8791
+ if (key === 'rowTree' || key === 'columnTree' || key === 'columnTreeRowEndIndex') {
8792
+ self.initCellTreeSettings();
8793
+ }
8794
+
7131
8795
  self.draw(true);
7132
8796
  self.dispatchEvent('attributechanged', {
7133
8797
  name: key,
@@ -7762,6 +9426,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
7762
9426
  self.dispatchEvent('datachanged', {
7763
9427
  data: self.originalData
7764
9428
  });
9429
+ self.initCellTreeSettings();
7765
9430
  self.resize(true);
7766
9431
  });
7767
9432
  }
@@ -8111,6 +9776,12 @@ __webpack_require__.r(__webpack_exports__);
8111
9776
  /*globals define: true, MutationObserver: false, requestAnimationFrame: false, performance: false, btoa: false*/
8112
9777
 
8113
9778
 
9779
+ 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; } } }; }
9780
+
9781
+ 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); }
9782
+
9783
+ 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; }
9784
+
8114
9785
  /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(self) {
8115
9786
  /**
8116
9787
  * Converts a integer into a letter A - ZZZZZ...
@@ -8457,6 +10128,62 @@ __webpack_require__.r(__webpack_exports__);
8457
10128
  left: cells[0].x + cells[0].width + offset.x
8458
10129
  }, items, imgSrc);
8459
10130
  };
10131
+ /**
10132
+ * Expand/Collapse CellTree.
10133
+ * @memberof canvasDatagrid
10134
+ * @name toggleCellCollapseTree
10135
+ * @method
10136
+ * @param {array} treeData The array of cellTree to expand or collapse.
10137
+ */
10138
+
10139
+
10140
+ self.toggleCellCollapseTree = function (treeData) {
10141
+ for (var type in treeData) {
10142
+ var _iterator = _createForOfIteratorHelper(treeData[type]),
10143
+ _step;
10144
+
10145
+ try {
10146
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
10147
+ var t = _step.value;
10148
+ if (t.length > 0) self.toggleCollapseTree(t[0], t[1], type);
10149
+ }
10150
+ } catch (err) {
10151
+ _iterator.e(err);
10152
+ } finally {
10153
+ _iterator.f();
10154
+ }
10155
+ }
10156
+
10157
+ self.draw();
10158
+ };
10159
+ /**
10160
+ * Expand/Collapse CellTree.
10161
+ * @memberof canvasDatagrid
10162
+ * @name expandCollapseCellTree
10163
+ * @method
10164
+ * @param {array} treeData The array of cellTree to expand or collapse.
10165
+ */
10166
+
10167
+
10168
+ self.expandCollapseCellTree = function (treeData) {
10169
+ for (var type in treeData) {
10170
+ var _iterator2 = _createForOfIteratorHelper(treeData[type]),
10171
+ _step2;
10172
+
10173
+ try {
10174
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
10175
+ var t = _step2.value;
10176
+ if (t.length > 0) self.cellTreeExpandCollapse(t[0], t[1], type);
10177
+ }
10178
+ } catch (err) {
10179
+ _iterator2.e(err);
10180
+ } finally {
10181
+ _iterator2.f();
10182
+ }
10183
+ }
10184
+
10185
+ self.draw();
10186
+ };
8460
10187
  /**
8461
10188
  * Scrolls the cell at cell x, row y into view if it is not already.
8462
10189
  * @memberof canvasDatagrid
@@ -8470,9 +10197,16 @@ __webpack_require__.r(__webpack_exports__);
8470
10197
 
8471
10198
 
8472
10199
  self.scrollIntoView = function (x, y, offsetX, offsetY) {
8473
- if (self.visibleCells.filter(function (cell) {
10200
+ var matched = self.visibleCells.filter(function (cell) {
8474
10201
  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;
8475
- }).length === 0) {
10202
+ });
10203
+
10204
+ if (matched.length === 1 && x !== undefined && y !== undefined) {
10205
+ // goto specific cell and its part be hidden by header
10206
+ if (matched[0].x < self.getRowHeaderCellWidth() || matched[0].y < self.getColumnHeaderCellHeight()) matched.length = 0;
10207
+ }
10208
+
10209
+ if (matched.length === 0) {
8476
10210
  self.gotoCell(x, y, offsetX, offsetY);
8477
10211
  }
8478
10212
  };
@@ -9001,6 +10735,315 @@ __webpack_require__.r(__webpack_exports__);
9001
10735
 
9002
10736
  self.setStorageData();
9003
10737
  };
10738
+ /**
10739
+ * Add grouping
10740
+ * @param {'columns'|'rows'} groupFor
10741
+ * @param {number} from
10742
+ * @param {number} to
10743
+ */
10744
+
10745
+
10746
+ function addGroup(groupFor, from, to) {
10747
+ var newRow = false;
10748
+ var allGroups = groupFor === 'rows' ? self.groupedRows : self.groupedColumns;
10749
+
10750
+ for (var i = allGroups.length - 1; i >= 0; i--) {
10751
+ var groups = allGroups[i];
10752
+ var min = groups[0].from,
10753
+ max = groups[groups.length - 1].to;
10754
+
10755
+ if (from <= min && to >= max) {
10756
+ if (from === min && to === max && groups.length === 1) return; // nothings happened
10757
+ // new group wrap this row
10758
+
10759
+ continue;
10760
+ }
10761
+
10762
+ for (var gi = 0; gi < groups.length; gi++) {
10763
+ var g = groups[gi];
10764
+ if (from > g.to) continue;
10765
+
10766
+ if (from >= g.from) {
10767
+ if (to > g.to) {
10768
+ if (from === g.from) {
10769
+ allGroups.splice(i, 0, [{
10770
+ from: from,
10771
+ to: to,
10772
+ collapsed: false
10773
+ }]);
10774
+ self.refresh();
10775
+ return;
10776
+ }
10777
+
10778
+ throw new Error("Can't group these ".concat(groupFor));
10779
+ }
10780
+
10781
+ if (to === g.to) {
10782
+ if (from === g.from) return; // nothings happened
10783
+ }
10784
+
10785
+ newRow = true;
10786
+ break;
10787
+ }
10788
+
10789
+ if (to >= g.from) {
10790
+ if (to < g.to) throw new Error("Can't group these ".concat(groupFor));
10791
+ allGroups.splice(i, 0, [{
10792
+ from: from,
10793
+ to: to,
10794
+ collapsed: false
10795
+ }]);
10796
+ } else {
10797
+ groups.splice(gi, 0, {
10798
+ from: from,
10799
+ to: to,
10800
+ collapsed: false
10801
+ });
10802
+ }
10803
+
10804
+ self.refresh();
10805
+ return;
10806
+ }
10807
+
10808
+ if (newRow) continue;
10809
+ groups.push({
10810
+ from: from,
10811
+ to: to,
10812
+ collapsed: false
10813
+ });
10814
+ self.refresh();
10815
+ return;
10816
+ }
10817
+
10818
+ if (newRow) allGroups.push([{
10819
+ from: from,
10820
+ to: to,
10821
+ collapsed: false
10822
+ }]);else allGroups.unshift([{
10823
+ from: from,
10824
+ to: to,
10825
+ collapsed: false
10826
+ }]);
10827
+ self.refresh();
10828
+ }
10829
+ /**
10830
+ * Remove grouping
10831
+ * @param {Array<Array<{from:number,to:number,collapsed:boolean}>>} allGroups
10832
+ * @param {number} from
10833
+ * @param {number} to
10834
+ */
10835
+
10836
+
10837
+ function removeGroup(allGroups, from, to) {
10838
+ for (var i = 0; i < allGroups.length; i++) {
10839
+ var groups = allGroups[i];
10840
+
10841
+ for (var gi = 0; gi < groups.length; gi++) {
10842
+ var group = groups[gi];
10843
+
10844
+ if (group.from === from && group.to === to) {
10845
+ if (groups.length <= 1) allGroups.splice(i, 1);else groups.splice(gi, 1);
10846
+ self.refresh();
10847
+ return;
10848
+ }
10849
+ }
10850
+ }
10851
+ }
10852
+ /**
10853
+ * Grouping columns
10854
+ * @memberof canvasDatagrid
10855
+ * @name groupColumns
10856
+ * @method
10857
+ * @param {number|string} firstColumnName Name of the first column to be grouped.
10858
+ * @param {number|string} lastColumnName Name of the last column to be grouped.
10859
+ */
10860
+
10861
+
10862
+ self.groupColumns = function (firstColumnName, lastColumnName) {
10863
+ /** @type {Array<{name: string,columnIndex:number}>} */
10864
+ var schema = self.getSchema();
10865
+ var firstOne, lastOne;
10866
+
10867
+ for (var i = 0; i < schema.length; i++) {
10868
+ var it = schema[i];
10869
+ if (firstOne && lastOne) break;
10870
+
10871
+ if (it.name === firstColumnName) {
10872
+ firstOne = it;
10873
+ continue;
10874
+ }
10875
+
10876
+ if (it.name === lastColumnName) {
10877
+ lastOne = it;
10878
+ continue;
10879
+ }
10880
+ }
10881
+
10882
+ if (!firstOne) throw new Error("No such column name for first column");
10883
+ if (!lastOne) throw new Error("No such column name for last column");
10884
+ if (lastOne.columnIndex > firstOne.columnIndex !== true) throw new Error("Can't group these columns");
10885
+ var from = firstOne.columnIndex;
10886
+ var to = lastOne.columnIndex;
10887
+ var ev = {
10888
+ group: {
10889
+ type: 'columns',
10890
+ from: from,
10891
+ to: to
10892
+ }
10893
+ };
10894
+
10895
+ try {
10896
+ addGroup('columns', from, to);
10897
+ } catch (error) {
10898
+ ev.error = error;
10899
+ }
10900
+
10901
+ self.dispatchEvent('aftercreategroup', ev);
10902
+ };
10903
+ /**
10904
+ * Grouping columns
10905
+ * @memberof canvasDatagrid
10906
+ * @name groupRows
10907
+ * @method
10908
+ * @param {number} rowIndexFrom The row index which is the beginning of the group
10909
+ * @param {number} rowIndexTo The row index which is the end of the group
10910
+ */
10911
+
10912
+
10913
+ self.groupRows = function (rowIndexFrom, rowIndexTo) {
10914
+ if (!Number.isInteger(rowIndexFrom) || rowIndexFrom < 0) throw new Error("No such row for the beginning of the group");
10915
+ var dataLength = self.viewData.length;
10916
+ if (!Number.isInteger(rowIndexFrom) || rowIndexTo <= rowIndexFrom || rowIndexTo >= dataLength) throw new Error("No such row for the end of the group");
10917
+ var ev = {
10918
+ group: {
10919
+ type: 'rows',
10920
+ from: rowIndexFrom,
10921
+ to: rowIndexTo
10922
+ }
10923
+ };
10924
+
10925
+ try {
10926
+ addGroup('rows', rowIndexFrom, rowIndexTo);
10927
+ } catch (error) {
10928
+ ev.error = error;
10929
+ }
10930
+
10931
+ self.dispatchEvent('aftercreategroup', ev);
10932
+ };
10933
+ /**
10934
+ * Remove grouping columns
10935
+ * @memberof canvasDatagrid
10936
+ * @name removeGroupColumns
10937
+ * @method
10938
+ * @param {number|string} firstColumnName Name of the first column to be grouped.
10939
+ * @param {number|string} lastColumnName Name of the last column to be grouped.
10940
+ */
10941
+
10942
+
10943
+ self.removeGroupColumns = function (firstColumnName, lastColumnName) {
10944
+ /** @type {Array<{name:string,columnIndex:number}>} */
10945
+ var schema = self.getSchema();
10946
+ var firstOne, lastOne;
10947
+
10948
+ for (var i = 0; i < schema.length; i++) {
10949
+ var it = schema[i];
10950
+ if (firstOne && lastOne) break;
10951
+
10952
+ if (it.name === firstColumnName) {
10953
+ firstOne = it;
10954
+ continue;
10955
+ }
10956
+
10957
+ if (it.name === lastColumnName) {
10958
+ lastOne = it;
10959
+ continue;
10960
+ }
10961
+ }
10962
+
10963
+ if (!firstOne) throw new Error("No such column name for first column");
10964
+ if (!lastOne) throw new Error("No such column name for last column");
10965
+ var from = firstOne.columnIndex;
10966
+ var to = lastOne.columnIndex;
10967
+ removeGroup(self.groupedColumns, from, to);
10968
+ };
10969
+ /**
10970
+ * Remove grouping columns
10971
+ * @memberof canvasDatagrid
10972
+ * @name removeGroupRows
10973
+ * @method
10974
+ * @param {number} rowIndexFrom The row index which is the beginning of the group
10975
+ * @param {number} rowIndexTo The row index which is the end of the group
10976
+ */
10977
+
10978
+
10979
+ self.removeGroupRows = function (rowIndexFrom, rowIndexTo) {
10980
+ removeGroup(self.groupedRows, rowIndexFrom, rowIndexTo);
10981
+ };
10982
+ /**
10983
+ * Toggle(expand/collapsed) grouping columns
10984
+ * @memberof canvasDatagrid
10985
+ * @name toggleGroupColumns
10986
+ * @method
10987
+ * @param {number|string} firstColumnName Name of the first column to be grouped.
10988
+ * @param {number|string} lastColumnName Name of the last column to be grouped.
10989
+ */
10990
+
10991
+
10992
+ self.toggleGroupColumns = function (firstColumnName, lastColumnName) {
10993
+ /** @type {Array<{name:string,columnIndex:number}>} */
10994
+ var schema = self.getSchema();
10995
+ var firstOne, lastOne;
10996
+
10997
+ for (var i = 0; i < schema.length; i++) {
10998
+ var it = schema[i];
10999
+ if (firstOne && lastOne) break;
11000
+
11001
+ if (it.name === firstColumnName) {
11002
+ firstOne = it;
11003
+ continue;
11004
+ }
11005
+
11006
+ if (it.name === lastColumnName) {
11007
+ lastOne = it;
11008
+ continue;
11009
+ }
11010
+ }
11011
+
11012
+ if (!firstOne || !lastOne) return;
11013
+ var from = firstOne.columnIndex;
11014
+ var to = lastOne.columnIndex;
11015
+
11016
+ if (self.toggleGroup({
11017
+ type: 'c',
11018
+ from: from,
11019
+ to: to
11020
+ })) {
11021
+ self.disposeContextMenu();
11022
+ self.setStorageData();
11023
+ self.refresh();
11024
+ }
11025
+ };
11026
+ /**
11027
+ * Toggle(expand/collapsed) grouping rows
11028
+ * @memberof canvasDatagrid
11029
+ * @name toggleGroupRows
11030
+ * @method
11031
+ * @param {number} rowIndexFrom The row index which is the beginning of the group
11032
+ * @param {number} rowIndexTo The row index which is the end of the group
11033
+ */
11034
+
11035
+
11036
+ self.toggleGroupRows = function (rowIndexFrom, rowIndexTo) {
11037
+ if (self.toggleGroup({
11038
+ type: 'r',
11039
+ from: rowIndexFrom,
11040
+ to: rowIndexTo
11041
+ })) {
11042
+ self.disposeContextMenu();
11043
+ self.setStorageData();
11044
+ self.refresh();
11045
+ }
11046
+ };
9004
11047
 
9005
11048
  self.isInGrid = function (e) {
9006
11049
  if (e.x < 0 || e.x > self.width || e.y < 0 || e.y > self.height) {
@@ -9091,6 +11134,10 @@ __webpack_require__.r(__webpack_exports__);
9091
11134
  } // TODO:
9092
11135
 
9093
11136
 
11137
+ if (!self.data) {
11138
+ self.data = {};
11139
+ }
11140
+
9094
11141
  if (!self.data[rowIndex]) {
9095
11142
  self.data[rowIndex] = {};
9096
11143
  } // TODO:
@@ -9129,6 +11176,64 @@ __webpack_require__.r(__webpack_exports__);
9129
11176
  });
9130
11177
  });
9131
11178
  };
11179
+ /**
11180
+ * Get the column group info given column belongs to
11181
+ * @memberof canvasDatagrid
11182
+ * @name getGroupsColumnBelongsTo
11183
+ * @method
11184
+ * @param {number} columnIndex Column index.
11185
+ * @returns {Array<{from:number,to:number,collapsed:boolean}>}
11186
+ */
11187
+
11188
+
11189
+ self.getGroupsColumnBelongsTo = function (columnIndex) {
11190
+ if (!self.attributes.allowGroupingColumns) return [];
11191
+ var result = [];
11192
+
11193
+ for (var i = 0; i < self.groupedColumns.length; i++) {
11194
+ var groups = self.groupedColumns[i];
11195
+
11196
+ for (var j = 0; j < groups.length; j++) {
11197
+ var group = groups[j];
11198
+
11199
+ if (columnIndex >= group.from && columnIndex <= group.to) {
11200
+ result.push(group);
11201
+ break;
11202
+ }
11203
+ }
11204
+ }
11205
+
11206
+ return result;
11207
+ };
11208
+ /**
11209
+ * Get the row group info given row belongs to
11210
+ * @memberof canvasDatagrid
11211
+ * @name getGroupsRowBelongsTo
11212
+ * @method
11213
+ * @param {number} rowIndex Row index.
11214
+ * @returns {Array<{from:number,to:number,collapsed:boolean}>}
11215
+ */
11216
+
11217
+
11218
+ self.getGroupsRowBelongsTo = function (rowIndex) {
11219
+ if (!self.attributes.allowGroupingRows) return [];
11220
+ var result = [];
11221
+
11222
+ for (var i = 0; i < self.groupedRows.length; i++) {
11223
+ var groups = self.groupedRows[i];
11224
+
11225
+ for (var j = 0; j < groups.length; j++) {
11226
+ var group = groups[j];
11227
+
11228
+ if (rowIndex >= group.from && rowIndex <= group.to) {
11229
+ result.push(group);
11230
+ break;
11231
+ }
11232
+ }
11233
+ }
11234
+
11235
+ return result;
11236
+ };
9132
11237
  /**
9133
11238
  * Checks if a given column is visible.
9134
11239
  * @memberof canvasDatagrid
@@ -9175,6 +11280,50 @@ __webpack_require__.r(__webpack_exports__);
9175
11280
  return c.columnIndex === x && c.rowIndex === y;
9176
11281
  })[0];
9177
11282
  };
11283
+ /**
11284
+ * Get a column group at grid pixel coordinate x and y.
11285
+ * @memberof canvasDatagrid
11286
+ * @name getColumnGroupAt
11287
+ * @method
11288
+ * @param {number} x Number of pixels from the left.
11289
+ * @param {number} y Number of pixels from the top.
11290
+ */
11291
+
11292
+
11293
+ self.getColumnGroupAt = function (x, y) {
11294
+ var groups = self.groupedColumns.length;
11295
+ if (groups <= 0) return;
11296
+ var yZero = self.getColumnGroupAreaHeight();
11297
+ if (y >= yZero) return;
11298
+
11299
+ for (var i = 0; i < self.visibleGroups.length; i++) {
11300
+ var g = self.visibleGroups[i];
11301
+ if (g.type !== 'c') continue;
11302
+ if (x >= g.x && y >= g.y && x <= g.x2 && y <= g.y2) return g;
11303
+ }
11304
+ };
11305
+ /**
11306
+ * Get a row group at grid pixel coordinate x and y.
11307
+ * @memberof canvasDatagrid
11308
+ * @name getRowGroupAt
11309
+ * @method
11310
+ * @param {number} x Number of pixels from the left.
11311
+ * @param {number} y Number of pixels from the top.
11312
+ */
11313
+
11314
+
11315
+ self.getRowGroupAt = function (x, y) {
11316
+ var groups = self.groupedRows.length;
11317
+ if (groups <= 0) return;
11318
+ var xZero = self.getRowGroupAreaWidth();
11319
+ if (x >= xZero) return;
11320
+
11321
+ for (var i = 0; i < self.visibleGroups.length; i++) {
11322
+ var g = self.visibleGroups[i];
11323
+ if (g.type !== 'r') continue;
11324
+ if (x >= g.x && y >= g.y && x <= g.x2 && y <= g.y2) return g;
11325
+ }
11326
+ };
9178
11327
  /**
9179
11328
  * 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.
9180
11329
  * @memberof canvasDatagrid
@@ -9209,6 +11358,8 @@ __webpack_require__.r(__webpack_exports__);
9209
11358
  return;
9210
11359
  }
9211
11360
 
11361
+ x -= self.getRowGroupAreaWidth();
11362
+ y -= self.getColumnGroupAreaHeight();
9212
11363
  var border,
9213
11364
  tsz = useTouchScrollZones ? self.attributes.touchScrollZone : 0,
9214
11365
  moveMode = self.attributes.borderDragBehavior === 'move',
@@ -9339,8 +11490,14 @@ __webpack_require__.r(__webpack_exports__);
9339
11490
  }
9340
11491
 
9341
11492
  if (cell.style === 'columnHeaderCell') {
9342
- cell.context = 'cell';
9343
- cell.dragContext = 'column-reorder';
11493
+ if (cell.x + cell.width - self.attributes.columnGrabZoneSize - self.style.cellBorderWidth > x || !self.attributes.allowRowReordering) {
11494
+ cell.dragContext = 'cell';
11495
+ cell.context = 'cell';
11496
+ } else {
11497
+ cell.context = self.cursorGrab;
11498
+ cell.dragContext = 'column-reorder';
11499
+ }
11500
+
9344
11501
  return cell;
9345
11502
  }
9346
11503