tabulator-tables 5.5.4 → 5.6.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.
Files changed (101) hide show
  1. package/bower.json +1 -1
  2. package/dist/css/tabulator.css +72 -2
  3. package/dist/css/tabulator.css.map +1 -1
  4. package/dist/css/tabulator.min.css +1 -1
  5. package/dist/css/tabulator.min.css.map +1 -1
  6. package/dist/css/tabulator_bootstrap3.css +72 -2
  7. package/dist/css/tabulator_bootstrap3.css.map +1 -1
  8. package/dist/css/tabulator_bootstrap3.min.css +1 -1
  9. package/dist/css/tabulator_bootstrap3.min.css.map +1 -1
  10. package/dist/css/tabulator_bootstrap4.css +72 -2
  11. package/dist/css/tabulator_bootstrap4.css.map +1 -1
  12. package/dist/css/tabulator_bootstrap4.min.css +1 -1
  13. package/dist/css/tabulator_bootstrap4.min.css.map +1 -1
  14. package/dist/css/tabulator_bootstrap5.css +72 -2
  15. package/dist/css/tabulator_bootstrap5.css.map +1 -1
  16. package/dist/css/tabulator_bootstrap5.min.css +1 -1
  17. package/dist/css/tabulator_bootstrap5.min.css.map +1 -1
  18. package/dist/css/tabulator_bulma.css +72 -2
  19. package/dist/css/tabulator_bulma.css.map +1 -1
  20. package/dist/css/tabulator_bulma.min.css +1 -1
  21. package/dist/css/tabulator_bulma.min.css.map +1 -1
  22. package/dist/css/tabulator_materialize.css +72 -2
  23. package/dist/css/tabulator_materialize.css.map +1 -1
  24. package/dist/css/tabulator_materialize.min.css +1 -1
  25. package/dist/css/tabulator_materialize.min.css.map +1 -1
  26. package/dist/css/tabulator_midnight.css +72 -2
  27. package/dist/css/tabulator_midnight.css.map +1 -1
  28. package/dist/css/tabulator_midnight.min.css +1 -1
  29. package/dist/css/tabulator_midnight.min.css.map +1 -1
  30. package/dist/css/tabulator_modern.css +72 -2
  31. package/dist/css/tabulator_modern.css.map +1 -1
  32. package/dist/css/tabulator_modern.min.css +1 -1
  33. package/dist/css/tabulator_modern.min.css.map +1 -1
  34. package/dist/css/tabulator_semanticui.css +72 -2
  35. package/dist/css/tabulator_semanticui.css.map +1 -1
  36. package/dist/css/tabulator_semanticui.min.css +1 -1
  37. package/dist/css/tabulator_semanticui.min.css.map +1 -1
  38. package/dist/css/tabulator_simple.css +72 -2
  39. package/dist/css/tabulator_simple.css.map +1 -1
  40. package/dist/css/tabulator_simple.min.css +1 -1
  41. package/dist/css/tabulator_simple.min.css.map +1 -1
  42. package/dist/css/tabulator_site.css +74 -4
  43. package/dist/css/tabulator_site.css.map +1 -1
  44. package/dist/css/tabulator_site.min.css +1 -1
  45. package/dist/css/tabulator_site.min.css.map +1 -1
  46. package/dist/js/tabulator.js +1868 -245
  47. package/dist/js/tabulator.js.map +1 -1
  48. package/dist/js/tabulator.min.js +2 -2
  49. package/dist/js/tabulator.min.js.map +1 -1
  50. package/dist/js/tabulator_esm.js +1948 -323
  51. package/dist/js/tabulator_esm.js.map +1 -1
  52. package/dist/js/tabulator_esm.min.js +2 -2
  53. package/dist/js/tabulator_esm.min.js.map +1 -1
  54. package/package.json +2 -2
  55. package/src/js/core/ColumnManager.js +4 -0
  56. package/src/js/core/CoreFeature.js +2 -2
  57. package/src/js/core/RowManager.js +12 -6
  58. package/src/js/core/Tabulator.js +2 -1
  59. package/src/js/core/TabulatorFull.js +1 -1
  60. package/src/js/core/column/Column.js +10 -0
  61. package/src/js/core/modules/optional.js +2 -1
  62. package/src/js/core/rendering/renderers/BasicVertical.js +4 -2
  63. package/src/js/core/rendering/renderers/VirtualDomHorizontal.js +1 -1
  64. package/src/js/core/row/PseudoRow.js +2 -0
  65. package/src/js/core/tools/Alert.js +4 -0
  66. package/src/js/core/tools/DeprecationAdvisor.js +5 -1
  67. package/src/js/core/tools/Helpers.js +1 -1
  68. package/src/js/core/tools/InteractionMonitor.js +3 -3
  69. package/src/js/modules/Clipboard/Clipboard.js +5 -3
  70. package/src/js/modules/Clipboard/defaults/pasteActions.js +49 -6
  71. package/src/js/modules/Clipboard/defaults/pasteParsers.js +69 -14
  72. package/src/js/modules/ColumnCalcs/ColumnCalcs.js +7 -1
  73. package/src/js/modules/Edit/Edit.js +71 -25
  74. package/src/js/modules/Edit/defaults/editors/datetime.js +1 -1
  75. package/src/js/modules/Edit/defaults/editors/time.js +3 -1
  76. package/src/js/modules/Export/Export.js +38 -18
  77. package/src/js/modules/Format/defaults/formatters/rowSelection.js +2 -2
  78. package/src/js/modules/Format/defaults/formatters/rownum.js +5 -1
  79. package/src/js/modules/FrozenColumns/FrozenColumns.js +11 -11
  80. package/src/js/modules/FrozenRows/FrozenRows.js +6 -1
  81. package/src/js/modules/History/History.js +2 -2
  82. package/src/js/modules/History/defaults/redoers.js +4 -0
  83. package/src/js/modules/History/defaults/undoers.js +4 -0
  84. package/src/js/modules/Keybindings/defaults/actions.js +38 -1
  85. package/src/js/modules/Keybindings/defaults/bindings.js +16 -1
  86. package/src/js/modules/Menu/Menu.js +3 -1
  87. package/src/js/modules/MoveColumns/MoveColumns.js +5 -0
  88. package/src/js/modules/Popup/Popup.js +1 -1
  89. package/src/js/modules/ResizeTable/ResizeTable.js +3 -3
  90. package/src/js/modules/SelectRange/Range.js +354 -0
  91. package/src/js/modules/SelectRange/RangeComponent.js +93 -0
  92. package/src/js/modules/SelectRange/SelectRange.js +870 -0
  93. package/src/js/modules/SelectRow/SelectRow.js +46 -26
  94. package/src/js/modules/Sort/Sort.js +111 -105
  95. package/src/js/modules/Validate/defaults/validators.js +11 -0
  96. package/src/scss/tabulator.scss +95 -13
  97. package/src/scss/themes/bulma/tabulator_bulma.scss +7 -0
  98. package/src/scss/themes/materialize/tabulator_materialize.scss +7 -1
  99. package/src/scss/themes/tabulator_midnight.scss +13 -0
  100. package/src/scss/themes/tabulator_modern.scss +9 -0
  101. package/src/scss/themes/tabulator_site.scss +13 -2
@@ -0,0 +1,870 @@
1
+ import Module from "../../core/Module.js";
2
+ import Range from "./Range.js";
3
+
4
+ class SelectRange extends Module {
5
+ constructor(table) {
6
+ super(table);
7
+
8
+ this.selecting = "cell";
9
+ this.mousedown = false;
10
+ this.ranges = [];
11
+ this.overlay = null;
12
+ this.rowHeader = null;
13
+ this.layoutChangeTimeout = null;
14
+ this.columnSelection = false;
15
+ this.rowSelection = false;
16
+ this.maxRanges = 0;
17
+ this.activeRange = false;
18
+ this.blockKeydown = false;
19
+
20
+ this.keyDownEvent = this._handleKeyDown.bind(this);
21
+ this.mouseUpEvent = this._handleMouseUp.bind(this);
22
+
23
+ this.registerTableOption("selectableRange", false); //enable selectable range
24
+ this.registerTableOption("selectableRangeColumns", false); //enable selectable range
25
+ this.registerTableOption("selectableRangeRows", false); //enable selectable range
26
+ this.registerTableOption("selectableRangeClearCells", false); //allow clearing of active range
27
+ this.registerTableOption("selectableRangeClearCellsValue", undefined); //value for cleared active range
28
+
29
+ this.registerTableFunction("getRangesData", this.getRangesData.bind(this));
30
+ this.registerTableFunction("getRanges", this.getRanges.bind(this));
31
+ this.registerTableFunction("addRange", this.addRangeFromComponent.bind(this));
32
+
33
+ this.registerComponentFunction("cell", "getRanges", this.cellGetRanges.bind(this));
34
+ this.registerComponentFunction("row", "getRanges", this.rowGetRanges.bind(this));
35
+ this.registerComponentFunction("column", "getRanges", this.colGetRanges.bind(this));
36
+ }
37
+
38
+ ///////////////////////////////////
39
+ /////// Initialization ///////
40
+ ///////////////////////////////////
41
+
42
+ initialize() {
43
+ if (this.options("selectableRange")) {
44
+ if(!this.options("selectableRows")){
45
+
46
+ this.maxRanges = this.options("selectableRange");
47
+
48
+ this.initializeTable();
49
+ this.initializeWatchers();
50
+ }else{
51
+ console.warn("SelectRange functionality cannot be used in conjunction with row selection");
52
+ }
53
+ }
54
+ }
55
+
56
+
57
+ initializeTable() {
58
+ this.overlay = document.createElement("div");
59
+ this.overlay.classList.add("tabulator-range-overlay");
60
+
61
+ this.rangeContainer = document.createElement("div");
62
+ this.rangeContainer.classList.add("tabulator-range-container");
63
+
64
+ this.activeRangeCellElement = document.createElement("div");
65
+ this.activeRangeCellElement.classList.add("tabulator-range-cell-active");
66
+
67
+ this.overlay.appendChild(this.rangeContainer);
68
+ this.overlay.appendChild(this.activeRangeCellElement);
69
+
70
+ this.table.rowManager.element.addEventListener("keydown", this.keyDownEvent);
71
+
72
+ this.resetRanges();
73
+
74
+ this.table.rowManager.element.appendChild(this.overlay);
75
+ this.table.columnManager.element.setAttribute("tabindex", 0);
76
+ this.table.element.classList.add("tabulator-ranges");
77
+ }
78
+
79
+ initializeWatchers() {
80
+ this.columnSelection = this.options("selectableRangeColumns");
81
+ this.rowSelection = this.options("selectableRangeRows");
82
+
83
+ this.subscribe("column-init", this.initializeColumn.bind(this));
84
+ this.subscribe("column-mousedown", this.handleColumnMouseDown.bind(this));
85
+ this.subscribe("column-mousemove", this.handleColumnMouseMove.bind(this));
86
+ this.subscribe("column-resized", this.handleColumnResized.bind(this));
87
+ this.subscribe("column-width", this.layoutChange.bind(this));
88
+ this.subscribe("column-height", this.layoutChange.bind(this));
89
+ this.subscribe("column-resized", this.layoutChange.bind(this));
90
+ this.subscribe("columns-loaded", this.updateHeaderColumn.bind(this));
91
+
92
+ this.subscribe("cell-height", this.layoutChange.bind(this));
93
+ this.subscribe("cell-rendered", this.renderCell.bind(this));
94
+ this.subscribe("cell-mousedown", this.handleCellMouseDown.bind(this));
95
+ this.subscribe("cell-mousemove", this.handleCellMouseMove.bind(this));
96
+ this.subscribe("cell-click", this.handleCellClick.bind(this));
97
+ this.subscribe("cell-editing", this.handleEditingCell.bind(this));
98
+
99
+ this.subscribe("page-changed", this.redraw.bind(this));
100
+
101
+ this.subscribe("scroll-vertical", this.layoutChange.bind(this));
102
+ this.subscribe("scroll-horizontal", this.layoutChange.bind(this));
103
+
104
+ this.subscribe("data-destroy", this.tableDestroyed.bind(this));
105
+ this.subscribe("data-processed", this.resetRanges.bind(this));
106
+
107
+ this.subscribe("table-layout", this.layoutElement.bind(this));
108
+ this.subscribe("table-redraw", this.redraw.bind(this));
109
+ this.subscribe("table-destroy", this.tableDestroyed.bind(this));
110
+
111
+ this.subscribe("edit-editor-clear", this.finishEditingCell.bind(this));
112
+ this.subscribe("edit-blur", this.restoreFocus.bind(this));
113
+
114
+ this.subscribe("keybinding-nav-prev", this.keyNavigate.bind(this, "left"));
115
+ this.subscribe("keybinding-nav-next", this.keyNavigate.bind(this, "right"));
116
+ this.subscribe("keybinding-nav-left", this.keyNavigate.bind(this, "left"));
117
+ this.subscribe("keybinding-nav-right", this.keyNavigate.bind(this, "right"));
118
+ this.subscribe("keybinding-nav-up", this.keyNavigate.bind(this, "up"));
119
+ this.subscribe("keybinding-nav-down", this.keyNavigate.bind(this, "down"));
120
+ this.subscribe("keybinding-nav-range", this.keyNavigateRange.bind(this));
121
+ }
122
+
123
+
124
+ initializeColumn(column) {
125
+ if(this.columnSelection && column.definition.headerSort && this.options("headerSortClickElement") !== "icon"){
126
+ console.warn("Using column headerSort with selectableRangeColumns option may result in unpredictable behavior. Consider using headerSortClickElement: 'icon'.");
127
+ }
128
+
129
+ if (column.modules.edit) {
130
+ // Block editor from taking action so we can trigger edit by
131
+ // double clicking.
132
+ // column.modules.edit.blocked = true;
133
+ }
134
+ }
135
+
136
+ updateHeaderColumn(){
137
+ if(this.rowSelection){
138
+ this.rowHeader = this.table.columnManager.getVisibleColumnsByIndex()[0];
139
+
140
+ if(this.rowHeader){
141
+ this.rowHeader.definition.cssClass = this.rowHeader.definition.cssClass + " tabulator-range-row-header";
142
+
143
+ if(this.rowHeader.definition.headerSort){
144
+ console.warn("Using column headerSort with selectableRangeRows option may result in unpredictable behavior");
145
+ }
146
+
147
+ if(this.rowHeader.definition.editor){
148
+ console.warn("Using column editor with selectableRangeRows option may result in unpredictable behavior");
149
+ }
150
+ }
151
+ }
152
+ }
153
+
154
+ ///////////////////////////////////
155
+ /////// Table Functions ///////
156
+ ///////////////////////////////////
157
+
158
+ getRanges(){
159
+ return this.ranges.map((range) => range.getComponent());
160
+ }
161
+
162
+ getRangesData() {
163
+ return this.ranges.map((range) => range.getData());
164
+ }
165
+
166
+ addRangeFromComponent(start, end){
167
+ start = start ? start._cell : null;
168
+ end = end ? end._cell : null;
169
+
170
+ return this.addRange(start, end);
171
+ }
172
+
173
+ ///////////////////////////////////
174
+ /////// Component Functions ///////
175
+ ///////////////////////////////////
176
+
177
+ cellGetRanges(cell){
178
+ var ranges = [];
179
+
180
+ if (cell.column === this.rowHeader) {
181
+ ranges = this.ranges.filter((range) => range.occupiesRow(cell.row));
182
+ } else {
183
+ ranges = this.ranges.filter((range) => range.occupies(cell));
184
+ }
185
+
186
+ return ranges.map((range) => range.getComponent());
187
+ }
188
+
189
+ rowGetRanges(row){
190
+ var ranges = this.ranges.filter((range) => range.occupiesRow(row));
191
+
192
+ return ranges.map((range) => range.getComponent());
193
+ }
194
+
195
+ colGetRanges(col){
196
+ var ranges = this.ranges.filter((range) => range.occupiesColumn(col));
197
+
198
+ return ranges.map((range) => range.getComponent());
199
+ }
200
+
201
+ ///////////////////////////////////
202
+ ////////// Event Handlers /////////
203
+ ///////////////////////////////////
204
+
205
+ _handleMouseUp(e){
206
+ this.mousedown = false;
207
+ document.removeEventListener("mouseup", this.mouseUpEvent);
208
+ }
209
+
210
+ _handleKeyDown(e) {
211
+ if (!this.blockKeydown && (!this.table.modules.edit || (this.table.modules.edit && !this.table.modules.edit.currentCell))) {
212
+ if (e.key === "Enter") {
213
+ // is editing a cell?
214
+ if (this.table.modules.edit && this.table.modules.edit.currentCell) {
215
+ return;
216
+ }
217
+
218
+ this.table.modules.edit.editCell(this.getActiveCell());
219
+
220
+ e.preventDefault();
221
+ }
222
+
223
+ if ((e.key === "Backspace" || e.key === "Delete") && this.options("selectableRangeClearCells")) {
224
+ if(this.activeRange){
225
+ this.activeRange.clearValues();
226
+ }
227
+ }
228
+ }
229
+ }
230
+
231
+ initializeFocus(cell){
232
+ var range;
233
+
234
+ try{
235
+ if (document.selection) { // IE
236
+ range = document.body.createTextRange();
237
+ range.moveToElementText(cell.getElement());
238
+ range.select();
239
+ } else if (window.getSelection) {
240
+ range = document.createRange();
241
+ range.selectNode(cell.getElement());
242
+ window.getSelection().removeAllRanges();
243
+ window.getSelection().addRange(range);
244
+ }
245
+ }catch(e){}
246
+ }
247
+
248
+ restoreFocus(element){
249
+ this.table.rowManager.element.focus();
250
+
251
+ return true;
252
+ }
253
+
254
+ ///////////////////////////////////
255
+ ////// Column Functionality ///////
256
+ ///////////////////////////////////
257
+
258
+ handleColumnResized(column) {
259
+ var selected;
260
+
261
+ if (this.selecting !== "column" && this.selecting !== "all") {
262
+ return;
263
+ }
264
+
265
+ selected = this.ranges.some((range) => range.occupiesColumn(column));
266
+
267
+ if (!selected) {
268
+ return;
269
+ }
270
+
271
+ this.ranges.forEach((range) => {
272
+ var selectedColumns = range.getColumns(true);
273
+
274
+ selectedColumns.forEach((selectedColumn) => {
275
+ if (selectedColumn !== column) {
276
+ selectedColumn.setWidth(column.width);
277
+ }
278
+ });
279
+ });
280
+ }
281
+
282
+ handleColumnMouseDown(event, column) {
283
+ if (event.button === 2 && (this.selecting === "column" || this.selecting === "all") && this.activeRange.occupiesColumn(column)) {
284
+ return;
285
+ }
286
+
287
+ this.mousedown = true;
288
+
289
+ document.addEventListener("mouseup", this.mouseUpEvent);
290
+
291
+ this.newSelection(event, column);
292
+ }
293
+
294
+ handleColumnMouseMove(e, column) {
295
+ if (column === this.rowHeader || !this.mousedown || this.selecting === 'all') {
296
+ return;
297
+ }
298
+
299
+ this.activeRange.setBounds(false, column, true);
300
+ }
301
+
302
+ ///////////////////////////////////
303
+ //////// Cell Functionality ///////
304
+ ///////////////////////////////////
305
+
306
+ renderCell(cell) {
307
+ var el = cell.getElement(),
308
+ rangeIdx = this.ranges.findIndex((range) => range.occupies(cell));
309
+
310
+ el.classList.toggle("tabulator-range-selected", rangeIdx !== -1);
311
+ el.classList.toggle("tabulator-range-only-cell-selected", this.ranges.length === 1 && this.ranges[0].atTopLeft(cell) && this.ranges[0].atBottomRight(cell));
312
+
313
+ el.dataset.range = rangeIdx;
314
+ }
315
+
316
+ handleCellMouseDown(event, cell) {
317
+ if (event.button === 2 && (this.activeRange.occupies(cell) || ((this.selecting === "row" || this.selecting === "all") && this.activeRange.occupiesRow(cell.row)))) {
318
+ return;
319
+ }
320
+
321
+ this.mousedown = true;
322
+
323
+ document.addEventListener("mouseup", this.mouseUpEvent);
324
+
325
+ this.newSelection(event, cell);
326
+ }
327
+
328
+ handleCellMouseMove(e, cell) {
329
+ if (!this.mousedown || this.selecting === "all") {
330
+ return;
331
+ }
332
+
333
+ this.activeRange.setBounds(false, cell, true);
334
+ }
335
+
336
+ handleCellClick(e, cell){
337
+ this.initializeFocus(cell);
338
+ }
339
+
340
+ handleEditingCell(cell) {
341
+ if(this.activeRange){
342
+ this.activeRange.setBounds(cell);
343
+ }
344
+ }
345
+
346
+ finishEditingCell() {
347
+ this.blockKeydown = true;
348
+ this.table.rowManager.element.focus();
349
+
350
+ setTimeout(() => {
351
+ this.blockKeydown = false;
352
+ }, 10);
353
+ }
354
+
355
+ ///////////////////////////////////
356
+ /////// Navigation ///////
357
+ ///////////////////////////////////
358
+
359
+ keyNavigate(dir, e){
360
+ if(this.navigate(false, false, dir)){
361
+ e.preventDefault();
362
+ }
363
+ }
364
+
365
+ keyNavigateRange(e, dir, jump, expand){
366
+ if(this.navigate(jump, expand, dir)){
367
+ e.preventDefault();
368
+ }
369
+ }
370
+
371
+ navigate(jump, expand, dir) {
372
+ var moved = false,
373
+ range, rangeEdge, nextRow, nextCol, row, column;
374
+
375
+ // Don't navigate while editing
376
+ if (this.table.modules.edit && this.table.modules.edit.currentCell) {
377
+ return false;
378
+ }
379
+
380
+ // If there are more than 1 range, use the active range and destroy the others
381
+ if (this.ranges.length > 1) {
382
+ this.ranges = this.ranges.filter((range) => {
383
+ if (range === this.activeRange) {
384
+ range.setEnd(range.start.row, range.start.col);
385
+ return true;
386
+ }
387
+ range.destroy();
388
+ return false;
389
+ });
390
+ }
391
+
392
+ range = this.activeRange;
393
+
394
+ rangeEdge = expand ? range.end : range.start;
395
+ nextRow = rangeEdge.row;
396
+ nextCol = rangeEdge.col;
397
+
398
+ if(jump){
399
+ switch(dir){
400
+ case "left":
401
+ nextCol = this.findJumpCellLeft(range.start.row, rangeEdge.col);
402
+ break;
403
+ case "right":
404
+ nextCol = this.findJumpCellRight(range.start.row, rangeEdge.col);
405
+ break;
406
+ case "up":
407
+ nextRow = this.findJumpCellUp(rangeEdge.row, range.start.col);
408
+ break;
409
+ case "down":
410
+ nextRow = this.findJumpCellDown(rangeEdge.row, range.start.col);
411
+ break;
412
+ }
413
+ }else{
414
+ if(expand){
415
+ if ((this.selecting === 'row' && (dir === 'left' || dir === 'right')) || (this.selecting === 'column' && (dir === 'up' || dir === 'down'))) {
416
+ return;
417
+ }
418
+ }
419
+
420
+ switch(dir){
421
+ case "left":
422
+ nextCol = Math.max(nextCol - 1, 0);
423
+ break;
424
+ case "right":
425
+ nextCol = Math.min(nextCol + 1, this.getTableColumns().length - 1);
426
+ break;
427
+ case "up":
428
+ nextRow = Math.max(nextRow - 1, 0);
429
+ break;
430
+ case "down":
431
+ nextRow = Math.min(nextRow + 1, this.getTableRows().length - 1);
432
+ break;
433
+ }
434
+ }
435
+
436
+ moved = nextCol !== rangeEdge.col || nextRow !== rangeEdge.row;
437
+
438
+ if(!expand){
439
+ range.setStart(nextRow, nextCol);
440
+ }
441
+
442
+ range.setEnd(nextRow, nextCol);
443
+
444
+ if(!expand){
445
+ this.selecting = "cell";
446
+ }
447
+
448
+ if (moved) {
449
+ row = this.getRowByRangePos(range.end.row);
450
+ column = this.getColumnByRangePos(range.end.col);
451
+
452
+ if ((dir === 'left' || dir === 'right') && column.getElement().parentNode === null) {
453
+ column.getComponent().scrollTo(undefined, false);
454
+ } else if ((dir === 'up' || dir === 'down') && row.getElement().parentNode === null) {
455
+ row.getComponent().scrollTo(undefined, false);
456
+ } else {
457
+ // Use faster autoScroll when the elements are on the DOM
458
+ this.autoScroll(range, row.getElement(), column.getElement());
459
+ }
460
+
461
+ this.layoutElement();
462
+
463
+ return true;
464
+ }
465
+ }
466
+
467
+ rangeRemoved(removed){
468
+ this.ranges = this.ranges.filter((range) => range !== removed);
469
+
470
+ if(this.activeRange === removed){
471
+ if(this.ranges.length){
472
+ this.activeRange = this.ranges[this.ranges.length - 1];
473
+ }else{
474
+ this.addRange();
475
+ }
476
+ }
477
+
478
+ this.layoutElement();
479
+ }
480
+
481
+ findJumpCell(cells, reverse, emptyStart, emptySide){
482
+ var nextCell;
483
+
484
+ if(reverse){
485
+ cells = cells.reverse();
486
+ }
487
+
488
+ for(let currentCell of cells){
489
+ let currentValue = currentCell.getValue();
490
+
491
+ if(emptyStart){
492
+ nextCell = currentCell;
493
+ if(currentValue){
494
+ break;
495
+ }
496
+ }else{
497
+ if(emptySide){
498
+ nextCell = currentCell;
499
+
500
+ if(currentValue){
501
+ break;
502
+ }
503
+ }else{
504
+ if(currentValue){
505
+ nextCell = currentCell;
506
+ }else{
507
+ break;
508
+ }
509
+ }
510
+ }
511
+ }
512
+
513
+ return nextCell;
514
+ }
515
+
516
+ findJumpCellLeft(rowPos, colPos){
517
+ var row = this.getRowByRangePos(rowPos),
518
+ cells = row.cells.filter((cell) => cell.column.visible),
519
+ isStartingCellEmpty = !cells[colPos].getValue(),
520
+ isLeftOfStartingCellEmpty = cells[colPos] ? !cells[colPos].getValue() : false,
521
+ jumpCol = colPos,
522
+ targetCells = this.rowHeader ? cells.slice(1, colPos) : cells.slice(0, colPos),
523
+ nextCell = this.findJumpCell(targetCells, true, isStartingCellEmpty, isLeftOfStartingCellEmpty);
524
+
525
+ if(nextCell){
526
+ jumpCol = nextCell.column.getPosition() - 1;
527
+ }
528
+
529
+ return jumpCol;
530
+ }
531
+
532
+ findJumpCellRight(rowPos, colPos){
533
+ var row = this.getRowByRangePos(rowPos),
534
+ cells = row.cells.filter((cell) => cell.column.visible),
535
+ isStartingCellEmpty = !cells[colPos].getValue(),
536
+ isRightOfStartingCellEmpty = cells[colPos + 1] ? !cells[colPos + 1].getValue() : false,
537
+ jumpCol = colPos,
538
+ nextCell = this.findJumpCell(cells.slice(colPos + 1, cells.length), false, isStartingCellEmpty, isRightOfStartingCellEmpty);
539
+
540
+ if(nextCell){
541
+ jumpCol = nextCell.column.getPosition() - 1;
542
+ }
543
+
544
+ return jumpCol;
545
+ }
546
+
547
+ findJumpCellUp(rowPos, colPos) {
548
+ var column = this.getColumnByRangePos(colPos),
549
+ cells = column.cells.filter((cell) => this.table.rowManager.activeRows.includes(cell.row)),
550
+ isStartingCellEmpty = !cells[rowPos].getValue(),
551
+ isTopOfStartingCellEmpty = cells[rowPos - 1] ? !cells[rowPos - 1].getValue() : false,
552
+ jumpRow = rowPos,
553
+ nextCell = this.findJumpCell(cells.slice(0, jumpRow), true, isStartingCellEmpty, isTopOfStartingCellEmpty);
554
+
555
+ if(nextCell){
556
+ jumpRow = nextCell.row.position - 1;
557
+ }
558
+
559
+ return jumpRow;
560
+ }
561
+
562
+ findJumpCellDown(rowPos, colPos) {
563
+ var column = this.getColumnByRangePos(colPos),
564
+ cells = column.cells.filter((cell) => this.table.rowManager.activeRows.includes(cell.row)),
565
+ isStartingCellEmpty = !cells[rowPos].getValue(),
566
+ isBottomOfStartingCellEmpty = cells[rowPos + 1] ? !cells[rowPos + 1].getValue() : false,
567
+ jumpRow = rowPos,
568
+ nextCell = this.findJumpCell(cells.slice(jumpRow + 1, cells.length), false, isStartingCellEmpty, isBottomOfStartingCellEmpty);
569
+
570
+ if(nextCell){
571
+ jumpRow = nextCell.row.position - 1;
572
+ }
573
+
574
+ return jumpRow;
575
+ }
576
+
577
+ ///////////////////////////////////
578
+ /////// Selection ///////
579
+ ///////////////////////////////////
580
+ newSelection(event, element) {
581
+ var range;
582
+
583
+ if (element.type === "column") {
584
+ if(!this.columnSelection){
585
+ return;
586
+ }
587
+
588
+ if (element === this.rowHeader) {
589
+ range = this.resetRanges();
590
+ this.selecting = "all";
591
+
592
+ var topLeftCell, bottomRightCell = this.getCell(-1, -1);
593
+
594
+ if(this.rowHeader){
595
+ topLeftCell = this.getCell(0, 1);
596
+ }else{
597
+ topLeftCell = this.getCell(0, 0);
598
+ }
599
+
600
+ range.setBounds(topLeftCell, bottomRightCell);
601
+ return;
602
+ } else {
603
+ this.selecting = "column";
604
+ }
605
+ } else if (element.column === this.rowHeader) {
606
+ this.selecting = "row";
607
+ } else {
608
+ this.selecting = "cell";
609
+ }
610
+
611
+ if (event.shiftKey) {
612
+ this.activeRange.setBounds(false, element);
613
+ } else if (event.ctrlKey) {
614
+ this.addRange().setBounds(element);
615
+ } else {
616
+ this.resetRanges().setBounds(element);
617
+ }
618
+ }
619
+
620
+ autoScroll(range, row, column) {
621
+ var tableHolder = this.table.rowManager.element,
622
+ rowHeader, rect, view, withinHorizontalView, withinVerticalView;
623
+
624
+ if (typeof row === 'undefined') {
625
+ row = this.getRowByRangePos(range.end.row).getElement();
626
+ }
627
+
628
+ if (typeof column === 'undefined') {
629
+ column = this.getColumnByRangePos(range.end.col).getElement();
630
+ }
631
+
632
+ if (this.rowHeader) {
633
+ rowHeader = this.rowHeader.getElement();
634
+ }
635
+
636
+ rect = {
637
+ left: column.offsetLeft,
638
+ right: column.offsetLeft + column.offsetWidth,
639
+ top: row.offsetTop,
640
+ bottom: row.offsetTop + row.offsetHeight,
641
+ };
642
+
643
+ view = {
644
+ left: tableHolder.scrollLeft,
645
+ right: Math.ceil(tableHolder.scrollLeft + tableHolder.clientWidth),
646
+ top: tableHolder.scrollTop,
647
+ bottom: tableHolder.scrollTop + tableHolder.offsetHeight - this.table.rowManager.scrollbarWidth,
648
+ };
649
+
650
+ if (rowHeader) {
651
+ view.left += rowHeader.offsetWidth;
652
+ }
653
+
654
+ withinHorizontalView = view.left < rect.left && rect.left < view.right && view.left < rect.right && rect.right < view.right;
655
+
656
+ withinVerticalView = view.top < rect.top && rect.top < view.bottom && view.top < rect.bottom && rect.bottom < view.bottom;
657
+
658
+ if (!withinHorizontalView) {
659
+ if (rect.left < view.left) {
660
+ tableHolder.scrollLeft = rect.left;
661
+ if (rowHeader) {
662
+ tableHolder.scrollLeft -= rowHeader.offsetWidth;
663
+ }
664
+ } else if (rect.right > view.right) {
665
+ tableHolder.scrollLeft = rect.right - tableHolder.clientWidth;
666
+ }
667
+ }
668
+
669
+ if (!withinVerticalView) {
670
+ if (rect.top < view.top) {
671
+ tableHolder.scrollTop = rect.top;
672
+ } else if (rect.bottom > view.bottom) {
673
+ tableHolder.scrollTop = rect.bottom - tableHolder.clientHeight;
674
+ }
675
+ }
676
+ }
677
+
678
+
679
+ ///////////////////////////////////
680
+ /////// Layout ///////
681
+ ///////////////////////////////////
682
+
683
+ layoutChange(){
684
+ this.overlay.style.visibility = "hidden";
685
+ clearTimeout(this.layoutChangeTimeout);
686
+ this.layoutChangeTimeout = setTimeout(this.layoutRanges.bind(this), 200);
687
+ }
688
+
689
+ redraw(force) {
690
+ if (force) {
691
+ this.selecting = 'cell';
692
+ this.resetRanges();
693
+ this.layoutElement();
694
+ }
695
+ }
696
+
697
+ layoutElement(visibleRows) {
698
+ var rows;
699
+
700
+ if (visibleRows) {
701
+ rows = this.table.rowManager.getVisibleRows(true);
702
+ } else {
703
+ rows = this.table.rowManager.getRows();
704
+ }
705
+
706
+ rows.forEach((row) => {
707
+ if (row.type === "row") {
708
+ this.layoutRow(row);
709
+ row.cells.forEach((cell) => this.renderCell(cell));
710
+ }
711
+ });
712
+
713
+ this.getTableColumns().forEach((column) => {
714
+ this.layoutColumn(column);
715
+ });
716
+
717
+ this.layoutRanges();
718
+ }
719
+
720
+ layoutRow(row) {
721
+ var el = row.getElement(),
722
+ selected = false,
723
+ occupied = this.ranges.some((range) => range.occupiesRow(row));
724
+
725
+ if (this.selecting === "row") {
726
+ selected = occupied;
727
+ } else if (this.selecting === "all") {
728
+ selected = true;
729
+ }
730
+
731
+ el.classList.toggle("tabulator-range-selected", selected);
732
+ el.classList.toggle("tabulator-range-highlight", occupied);
733
+ }
734
+
735
+ layoutColumn(column) {
736
+ var el = column.getElement(),
737
+ selected = false,
738
+ occupied = this.ranges.some((range) => range.occupiesColumn(column));
739
+
740
+ if (this.selecting === "column") {
741
+ selected = occupied;
742
+ } else if (this.selecting === "all") {
743
+ selected = true;
744
+ }
745
+
746
+ el.classList.toggle("tabulator-range-selected", selected);
747
+ el.classList.toggle("tabulator-range-highlight", occupied);
748
+ }
749
+
750
+ layoutRanges() {
751
+ var activeCell;
752
+
753
+ if (!this.table.initialized) {
754
+ return;
755
+ }
756
+
757
+ activeCell = this.getActiveCell();
758
+
759
+ if (!activeCell) {
760
+ return;
761
+ }
762
+
763
+ this.activeRangeCellElement.style.left = activeCell.row.getElement().offsetLeft + activeCell.getElement().offsetLeft + "px";
764
+ this.activeRangeCellElement.style.top = activeCell.row.getElement().offsetTop + "px";
765
+ this.activeRangeCellElement.style.width = activeCell.getElement().offsetLeft + activeCell.getElement().offsetWidth - activeCell.getElement().offsetLeft + "px";
766
+ this.activeRangeCellElement.style.height = activeCell.row.getElement().offsetTop + activeCell.row.getElement().offsetHeight - activeCell.row.getElement().offsetTop + "px";
767
+
768
+ this.ranges.forEach((range) => range.layout());
769
+
770
+ this.overlay.style.visibility = "visible";
771
+ }
772
+
773
+
774
+ ///////////////////////////////////
775
+ /////// Helper Functions ///////
776
+ ///////////////////////////////////
777
+
778
+ getCell(rowIdx, colIdx) {
779
+ var row;
780
+
781
+ if (colIdx < 0) {
782
+ colIdx = this.getTableColumns().length + colIdx;
783
+ if (colIdx < 0) {
784
+ return null;
785
+ }
786
+ }
787
+
788
+ if (rowIdx < 0) {
789
+ rowIdx = this.getTableRows().length + rowIdx;
790
+ }
791
+
792
+ row = this.table.rowManager.getRowFromPosition(rowIdx + 1);
793
+
794
+ return row ? row.getCells(false, true).filter((cell) => cell.column.visible)[colIdx] : null;
795
+ }
796
+
797
+
798
+ getActiveCell() {
799
+ return this.getCell(this.activeRange.start.row, this.activeRange.start.col);
800
+ }
801
+
802
+ getRowByRangePos(pos) {
803
+ return this.getTableRows()[pos];
804
+ }
805
+
806
+ getColumnByRangePos(pos) {
807
+ return this.getTableColumns()[pos];
808
+ }
809
+
810
+ getTableRows() {
811
+ return this.table.rowManager.getDisplayRows();
812
+ }
813
+
814
+ getTableColumns() {
815
+ return this.table.columnManager.getVisibleColumnsByIndex();
816
+ }
817
+
818
+ addRange(start, end) {
819
+ var range;
820
+
821
+ if(this.maxRanges !== true && this.ranges.length >= this.maxRanges){
822
+ this.ranges.shift().destroy();
823
+ }
824
+
825
+ range = new Range(this.table, this, start, end);
826
+
827
+ this.activeRange = range;
828
+ this.ranges.push(range);
829
+ this.rangeContainer.appendChild(range.element);
830
+
831
+ return range;
832
+ }
833
+
834
+ resetRanges() {
835
+ var range, cell;
836
+
837
+ this.ranges.forEach((range) => range.destroy());
838
+ this.ranges = [];
839
+
840
+ range = this.addRange();
841
+
842
+ if(this.table.rowManager.activeRows.length){
843
+ cell = this.table.rowManager.activeRows[0].cells[this.rowHeader ? 1 : 0];
844
+
845
+ if(cell){
846
+ range.setBounds(cell);
847
+ this.initializeFocus(cell);
848
+ }
849
+ }
850
+
851
+ return range;
852
+ }
853
+
854
+ tableDestroyed(){
855
+ document.removeEventListener("mouseup", this.mouseUpEvent);
856
+ this.table.rowManager.element.removeEventListener("keydown", this.keyDownEvent);
857
+ }
858
+
859
+ selectedRows(component) {
860
+ return component ? this.activeRange.getRows().map((row) => row.getComponent()) : this.activeRange.getRows();
861
+ }
862
+
863
+ selectedColumns(component) {
864
+ return component ? this.activeRange.getColumns().map((col) => col.getComponent()) : this.activeRange.getColumns();
865
+ }
866
+ }
867
+
868
+ SelectRange.moduleName = "selectRange";
869
+
870
+ export default SelectRange;