canvas-datagrid 0.3.19 → 0.3.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/draw.js CHANGED
@@ -164,6 +164,34 @@ export default function (self) {
164
164
  self.ctx.fill();
165
165
  return ml + aw + mr;
166
166
  }
167
+ function drawFilterButtonArrow(x, y) {
168
+ var mt =
169
+ ((self.style.filterButtonHeight - self.style.filterButtonArrowHeight) /
170
+ 2) *
171
+ self.scale,
172
+ ml =
173
+ ((self.style.filterButtonWidth - self.style.filterButtonArrowWidth) /
174
+ 2) *
175
+ self.scale,
176
+ aw = self.style.filterButtonArrowWidth * self.scale,
177
+ ah = self.style.filterButtonArrowHeight * self.scale;
178
+ x += self.canvasOffsetLeft;
179
+ y += self.canvasOffsetTop;
180
+ self.ctx.fillStyle = self.style.filterButtonArrowColor;
181
+ self.ctx.strokeStyle = self.style.filterButtonArrowBorderColor;
182
+ self.ctx.beginPath();
183
+ x = x + ml;
184
+ y = y + mt;
185
+
186
+ self.ctx.moveTo(x, y);
187
+ self.ctx.lineTo(x + aw, y);
188
+ self.ctx.lineTo(x + aw * 0.5, y + ah);
189
+ self.ctx.moveTo(x, y);
190
+
191
+ self.ctx.stroke();
192
+ self.ctx.fill();
193
+ return ml + aw;
194
+ }
167
195
  function radiusRect(x, y, w, h, radius) {
168
196
  x += self.canvasOffsetLeft;
169
197
  y += self.canvasOffsetTop;
@@ -816,6 +844,9 @@ export default function (self) {
816
844
  isCorner = /cornerCell/.test(cellStyle),
817
845
  isRowHeader = 'rowHeaderCell' === cellStyle,
818
846
  isColumnHeader = 'columnHeaderCell' === cellStyle,
847
+ isFilterable =
848
+ self.filterable.rows.includes(rowIndex) &&
849
+ self.filterable.columns.includes(headerIndex),
819
850
  wrap = self.style.cellWhiteSpace !== 'nowrap',
820
851
  selected =
821
852
  self.selections[rowOrderIndex] &&
@@ -824,6 +855,9 @@ export default function (self) {
824
855
  self.hovers.rowIndex === rowOrderIndex &&
825
856
  (self.attributes.hoverMode === 'row' ||
826
857
  self.hovers.columnIndex === columnOrderIndex),
858
+ openedFilter =
859
+ self.selectedFilterButton.rowIndex == rowIndex &&
860
+ self.selectedFilterButton.columnIndex == headerIndex,
827
861
  active =
828
862
  self.activeCell.rowIndex === rowOrderIndex &&
829
863
  self.activeCell.columnIndex === columnOrderIndex,
@@ -915,6 +949,8 @@ export default function (self) {
915
949
  isColumnHeader: isColumnHeader,
916
950
  isColumnHeaderCellCap: isColumnHeaderCellCap,
917
951
  isRowHeader: isRowHeader,
952
+ isFilterable: isFilterable,
953
+ openedFilter: openedFilter,
918
954
  rowOpen: rowOpen,
919
955
  header: header,
920
956
 
@@ -1114,6 +1150,10 @@ export default function (self) {
1114
1150
  }
1115
1151
  self.ctx.restore();
1116
1152
 
1153
+ if (isFilterable) {
1154
+ drawFilterButton(cell);
1155
+ }
1156
+
1117
1157
  // Gaps may occur in row numbers between consecutively rendered rows
1118
1158
  // when we are filtering. We draw attention to this by drawing a thick
1119
1159
  // border overlapping the two consecutive row headers. If sorting, visible
@@ -1154,6 +1194,34 @@ export default function (self) {
1154
1194
  return cell.width;
1155
1195
  };
1156
1196
  }
1197
+ function drawFilterButton(cell, ev) {
1198
+ var posX = cell.x + cell.width - self.style.filterButtonWidth - 1;
1199
+ var posY = cell.y + cell.height - self.style.filterButtonHeight - 2;
1200
+ if (self.dispatchEvent('beforerenderfilterbutton', ev)) {
1201
+ return;
1202
+ }
1203
+ self.ctx.save();
1204
+ self.ctx.strokeStyle = self.style.filterButtonBorderColor;
1205
+ self.ctx.fillStyle = self.style.filterButtonBackgroundColor;
1206
+ if (cell.openedFilter) {
1207
+ self.ctx.fillStyle = self.style.filterButtonActiveBackgroundColor;
1208
+ } else if (cell.hovered && self.hovers.onFilterButton) {
1209
+ self.ctx.fillStyle = self.style.filterButtonHoverBackgroundColor;
1210
+ }
1211
+ radiusRect(
1212
+ posX,
1213
+ posY,
1214
+ self.style.filterButtonWidth,
1215
+ self.style.filterButtonHeight,
1216
+ self.style.filterButtonBorderRadius,
1217
+ );
1218
+ self.ctx.stroke();
1219
+ self.ctx.fill();
1220
+ drawFilterButtonArrow(posX, posY);
1221
+ self.ctx.clip();
1222
+ self.dispatchEvent('afterrenderfilterbutton', ev);
1223
+ self.ctx.restore();
1224
+ }
1157
1225
  function drawRowHeader(rowData, rowIndex, rowOrderIndex) {
1158
1226
  if (self.attributes.showRowHeaders) {
1159
1227
  x = 0;
@@ -468,7 +468,18 @@ export default function (self) {
468
468
  self.hovers = {
469
469
  rowIndex: cell.rowIndex,
470
470
  columnIndex: cell.columnIndex,
471
+ onFilterButton: false,
471
472
  };
473
+ if (
474
+ cell.isFilterable &&
475
+ x > cell.x + cell.width - self.style.filterButtonWidth &&
476
+ x < cell.x + cell.width &&
477
+ y > cell.y + cell.height - self.style.filterButtonHeight &&
478
+ y < cell.y + cell.height
479
+ ) {
480
+ self.hovers.onFilterButton = true;
481
+ self.draw();
482
+ }
472
483
  }
473
484
  if (self.selecting || self.reorderObject) {
474
485
  delta = {
@@ -512,30 +523,57 @@ export default function (self) {
512
523
  ) {
513
524
  self.selectRow(cell.rowIndex, ctrl, null, true);
514
525
  } else if (self.attributes.selectionMode !== 'row') {
515
- if (!self.dragAddToSelection && cell.rowIndex !== undefined) {
516
- if (
517
- self.selections[cell.rowIndex] &&
518
- self.selections[cell.rowIndex].indexOf(cell.columnIndex) !== -1
519
- ) {
520
- self.selections[cell.rowIndex].splice(
521
- self.selections[cell.rowIndex].indexOf(cell.columnIndex),
522
- 1,
523
- );
526
+ if (cell.hovered && self.hovers.onFilterButton) {
527
+ if (cell.openedFilter) {
528
+ cell.openedFilter = false;
529
+ self.selectedFilterButton = {
530
+ columnIndex: -1,
531
+ rowIndex: -1,
532
+ };
533
+ } else {
534
+ self.selectedFilterButton.rowIndex = cell.rowIndex;
535
+ self.selectedFilterButton.columnIndex = cell.columnIndex;
536
+ self.contextmenuEvent(e, {
537
+ x: cell.x + cell.width - self.style.filterButtonWidth,
538
+ y: cell.y + cell.height,
539
+ rect: { left: 0, top: 0 },
540
+ });
524
541
  }
542
+ self.draw();
543
+ return;
525
544
  } else {
526
- self.selections[cell.rowIndex] =
527
- self.selections[cell.rowIndex] || [];
528
- if (
529
- self.selections[cell.rowIndex].indexOf(cell.columnIndex) === -1
530
- ) {
531
- self.selections[cell.rowIndex].push(cell.columnIndex);
532
- const event = {
533
- selections: self.selections,
534
- selectedData: self.getSelectedData(),
535
- selectedCells: self.getSelectedCells(),
536
- selectionBounds: self.getSelectionBounds(),
537
- };
538
- self.dispatchEvent('selectionchanged', event);
545
+ self.selectedFilterButton = {
546
+ columnIndex: -1,
547
+ rowIndex: -1,
548
+ };
549
+ if (self.hovers.onFilterButton) return;
550
+ if (!self.dragAddToSelection && cell.rowIndex !== undefined) {
551
+ if (
552
+ self.selections[cell.rowIndex] &&
553
+ self.selections[cell.rowIndex].indexOf(cell.columnIndex) !==
554
+ -1
555
+ ) {
556
+ self.selections[cell.rowIndex].splice(
557
+ self.selections[cell.rowIndex].indexOf(cell.columnIndex),
558
+ 1,
559
+ );
560
+ }
561
+ } else {
562
+ self.selections[cell.rowIndex] =
563
+ self.selections[cell.rowIndex] || [];
564
+ if (
565
+ self.selections[cell.rowIndex].indexOf(cell.columnIndex) ===
566
+ -1
567
+ ) {
568
+ self.selections[cell.rowIndex].push(cell.columnIndex);
569
+ var event = {
570
+ selections: self.selections,
571
+ selectedData: self.getSelectedData(),
572
+ selectedCells: self.getSelectedCells(),
573
+ selectionBounds: self.getSelectionBounds(),
574
+ };
575
+ self.dispatchEvent('selectionchanged', event);
576
+ }
539
577
  }
540
578
  }
541
579
  }
@@ -548,13 +586,18 @@ export default function (self) {
548
586
  dragBounds.right !== self.selectionBounds.right) &&
549
587
  !ctrl
550
588
  ) {
551
- self.selections = [];
589
+ if (!(cell.hovered && self.hovers.onFilterButton)) {
590
+ self.selections = [];
591
+ }
592
+ if (dragBounds.top === -1) {
593
+ dragBounds.top = 0;
594
+ }
552
595
  sBounds = dragBounds;
553
596
  if (self.attributes.selectionMode === 'row') {
554
597
  for (i = sBounds.top; i <= sBounds.bottom; i += 1) {
555
598
  self.selectRow(i, true, null, true);
556
599
  }
557
- } else if (dragBounds.top !== -1) {
600
+ } else {
558
601
  self.selectArea(sBounds, true);
559
602
  if (sBounds.left == -1 && sBounds.top !== sBounds.bottom)
560
603
  self.isMultiRowsSelected = true;
@@ -632,7 +675,9 @@ export default function (self) {
632
675
  -1 &&
633
676
  !ctrl
634
677
  ) {
635
- self.setActiveCell(i.columnIndex, i.rowIndex);
678
+ if (!self.hovers.onFilterButton) {
679
+ self.setActiveCell(i.columnIndex, i.rowIndex);
680
+ }
636
681
  }
637
682
  if (self.currentCell.context === 'cell') {
638
683
  if (self.currentCell.style === 'cornerCell') {
@@ -1173,8 +1218,12 @@ export default function (self) {
1173
1218
  !freeze &&
1174
1219
  !resize
1175
1220
  ) {
1176
- if (!(self.dragMode == 'row-reorder' && self.isMultiRowsSelected))
1221
+ if (
1222
+ !(self.dragMode == 'row-reorder' && self.isMultiRowsSelected) &&
1223
+ !(self.currentCell.hovered && self.hovers.onFilterButton)
1224
+ ) {
1177
1225
  self.selections = [];
1226
+ }
1178
1227
  }
1179
1228
  if (self.dragStartObject.isGrid) {
1180
1229
  return;
@@ -1556,7 +1605,10 @@ export default function (self) {
1556
1605
  self.currentCell.style === 'cornerCell'
1557
1606
  ) {
1558
1607
  self.autosize();
1559
- } else if (['cell', 'activeCell'].indexOf(self.currentCell.style) !== -1) {
1608
+ } else if (
1609
+ ['cell', 'activeCell'].includes(self.currentCell.style) &&
1610
+ !self.hovers.onFilterButton
1611
+ ) {
1560
1612
  self.beginEditAt(self.currentCell.columnIndex, self.currentCell.rowIndex);
1561
1613
  }
1562
1614
  };
package/lib/intf.js CHANGED
@@ -61,6 +61,14 @@ export default function (self, ctor) {
61
61
  trees: {},
62
62
  };
63
63
  self.selections = [];
64
+ self.filterable = {
65
+ rows: [],
66
+ columns: [],
67
+ };
68
+ self.selectedFilterButton = {
69
+ columnIndex: -1,
70
+ rowIndex: -1,
71
+ };
64
72
  self.hovers = {};
65
73
  self.attributes = {};
66
74
  self.style = {};
@@ -88,6 +96,7 @@ export default function (self, ctor) {
88
96
  self.eventNames = [
89
97
  'afterdraw',
90
98
  'afterrendercell',
99
+ 'afterrenderfilterbutton',
91
100
  'attributechanged',
92
101
  'beforebeginedit',
93
102
  'beforecreatecellgrid',
@@ -95,6 +104,7 @@ export default function (self, ctor) {
95
104
  'beforeendedit',
96
105
  'beforerendercell',
97
106
  'beforerendercellgrid',
107
+ 'beforerenderfilterbutton',
98
108
  'beginedit',
99
109
  'cellmouseout',
100
110
  'cellmouseover',
@@ -755,6 +765,7 @@ export default function (self, ctor) {
755
765
  self.intf.clearChangeLog = self.clearChangeLog;
756
766
  self.intf.gotoCell = self.gotoCell;
757
767
  self.intf.gotoRow = self.gotoRow;
768
+ self.intf.addButton = self.addButton;
758
769
  self.intf.getHeaderByName = self.getHeaderByName;
759
770
  self.intf.findColumnScrollLeft = self.findColumnScrollLeft;
760
771
  self.intf.findRowScrollTop = self.findRowScrollTop;
@@ -1534,6 +1545,9 @@ export default function (self, ctor) {
1534
1545
  if (!preventScrollEvent) {
1535
1546
  self.scroll();
1536
1547
  }
1548
+ if (self.button) {
1549
+ self.moveButtonPos();
1550
+ }
1537
1551
  }
1538
1552
  function setScrollLeft(value, preventScrollEvent) {
1539
1553
  if (isNaN(value)) {
@@ -1552,6 +1566,9 @@ export default function (self, ctor) {
1552
1566
  if (!preventScrollEvent) {
1553
1567
  self.scroll();
1554
1568
  }
1569
+ if (self.button) {
1570
+ self.moveButtonPos();
1571
+ }
1555
1572
  }
1556
1573
  self.scrollBox.toString = function () {
1557
1574
  return (
package/lib/main.js CHANGED
@@ -9,6 +9,7 @@ import events from './events';
9
9
  import touch from './touch';
10
10
  import intf from './intf';
11
11
  import contextMenu from './contextMenu';
12
+ import button from './button';
12
13
  import dom from './dom';
13
14
  import publicMethods from './publicMethods';
14
15
 
@@ -21,6 +22,7 @@ var modules = [
21
22
  touch,
22
23
  intf,
23
24
  contextMenu,
25
+ button,
24
26
  dom,
25
27
  publicMethods,
26
28
  ];
@@ -206,6 +206,18 @@ export default function (self) {
206
206
  delete self.columnFilters[column];
207
207
  } else {
208
208
  self.columnFilters[column] = value;
209
+ if (self.attributes.showFilterInCell) {
210
+ self.filterable.rows.push(0);
211
+ self.orders.columns.forEach(function (value, index) {
212
+ self.filterable.columns.push(index);
213
+ });
214
+ }
215
+ }
216
+ if (!Object.keys(self.columnFilters).length) {
217
+ self.filterable = {
218
+ rows: [],
219
+ columns: [],
220
+ };
209
221
  }
210
222
  self.refresh();
211
223
  };
@@ -294,6 +306,31 @@ export default function (self) {
294
306
  self.gotoRow = function (y) {
295
307
  self.gotoCell(0, y);
296
308
  };
309
+ /**
310
+ * Add a button into the cell.
311
+ * @memberof canvasDatagrid
312
+ * @name addButton
313
+ * @method
314
+ * @param {number} columnIndex The column index of the cell to to add a button.
315
+ * @param {number} rowIndex The row index of the cell to to add a button.
316
+ * @param {object} offset Offset how far go away from cell.
317
+ * @param {object} items a list of items to add into button menu.
318
+ * @param {string} imgSrc icon path to add into button.
319
+ */
320
+ self.addButton = function (columnIndex, rowIndex, offset, items, imgSrc) {
321
+ var cells = self.visibleCells.filter(function (c) {
322
+ return c.sortColumnIndex === columnIndex && c.sortRowIndex === rowIndex;
323
+ });
324
+
325
+ self.attachButton(
326
+ {
327
+ top: cells[0].y + cells[0].height + offset.y,
328
+ left: cells[0].x + cells[0].width + offset.x,
329
+ },
330
+ items,
331
+ imgSrc,
332
+ );
333
+ };
297
334
  /**
298
335
  * Scrolls the cell at cell x, row y into view if it is not already.
299
336
  * @memberof canvasDatagrid
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canvas-datagrid",
3
- "version": "0.3.19",
3
+ "version": "0.3.20",
4
4
  "description": "Canvas based data grid web component. Capable of displaying millions of contiguous hierarchical rows and columns without paging or loading, on a single canvas element.",
5
5
  "main": "./dist/canvas-datagrid.js",
6
6
  "module": "./dist/canvas-datagrid.module.js",