tabulator-tables 5.5.3 → 5.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/LICENSE +1 -1
  2. package/bower.json +1 -1
  3. package/dist/css/tabulator.css +72 -2
  4. package/dist/css/tabulator.css.map +1 -1
  5. package/dist/css/tabulator.min.css +1 -1
  6. package/dist/css/tabulator.min.css.map +1 -1
  7. package/dist/css/tabulator_bootstrap3.css +72 -2
  8. package/dist/css/tabulator_bootstrap3.css.map +1 -1
  9. package/dist/css/tabulator_bootstrap3.min.css +1 -1
  10. package/dist/css/tabulator_bootstrap3.min.css.map +1 -1
  11. package/dist/css/tabulator_bootstrap4.css +72 -2
  12. package/dist/css/tabulator_bootstrap4.css.map +1 -1
  13. package/dist/css/tabulator_bootstrap4.min.css +1 -1
  14. package/dist/css/tabulator_bootstrap4.min.css.map +1 -1
  15. package/dist/css/tabulator_bootstrap5.css +72 -2
  16. package/dist/css/tabulator_bootstrap5.css.map +1 -1
  17. package/dist/css/tabulator_bootstrap5.min.css +1 -1
  18. package/dist/css/tabulator_bootstrap5.min.css.map +1 -1
  19. package/dist/css/tabulator_bulma.css +72 -2
  20. package/dist/css/tabulator_bulma.css.map +1 -1
  21. package/dist/css/tabulator_bulma.min.css +1 -1
  22. package/dist/css/tabulator_bulma.min.css.map +1 -1
  23. package/dist/css/tabulator_materialize.css +72 -2
  24. package/dist/css/tabulator_materialize.css.map +1 -1
  25. package/dist/css/tabulator_materialize.min.css +1 -1
  26. package/dist/css/tabulator_materialize.min.css.map +1 -1
  27. package/dist/css/tabulator_midnight.css +72 -2
  28. package/dist/css/tabulator_midnight.css.map +1 -1
  29. package/dist/css/tabulator_midnight.min.css +1 -1
  30. package/dist/css/tabulator_midnight.min.css.map +1 -1
  31. package/dist/css/tabulator_modern.css +72 -2
  32. package/dist/css/tabulator_modern.css.map +1 -1
  33. package/dist/css/tabulator_modern.min.css +1 -1
  34. package/dist/css/tabulator_modern.min.css.map +1 -1
  35. package/dist/css/tabulator_semanticui.css +72 -2
  36. package/dist/css/tabulator_semanticui.css.map +1 -1
  37. package/dist/css/tabulator_semanticui.min.css +1 -1
  38. package/dist/css/tabulator_semanticui.min.css.map +1 -1
  39. package/dist/css/tabulator_simple.css +72 -2
  40. package/dist/css/tabulator_simple.css.map +1 -1
  41. package/dist/css/tabulator_simple.min.css +1 -1
  42. package/dist/css/tabulator_simple.min.css.map +1 -1
  43. package/dist/css/tabulator_site.css +74 -4
  44. package/dist/css/tabulator_site.css.map +1 -1
  45. package/dist/css/tabulator_site.min.css +1 -1
  46. package/dist/css/tabulator_site.min.css.map +1 -1
  47. package/dist/js/tabulator.js +1830 -244
  48. package/dist/js/tabulator.js.map +1 -1
  49. package/dist/js/tabulator.min.js +2 -2
  50. package/dist/js/tabulator.min.js.map +1 -1
  51. package/dist/js/tabulator_esm.js +1900 -312
  52. package/dist/js/tabulator_esm.js.map +1 -1
  53. package/dist/js/tabulator_esm.min.js +2 -2
  54. package/dist/js/tabulator_esm.min.js.map +1 -1
  55. package/package.json +3 -5
  56. package/src/js/core/ColumnManager.js +4 -0
  57. package/src/js/core/CoreFeature.js +2 -2
  58. package/src/js/core/RowManager.js +9 -1
  59. package/src/js/core/Tabulator.js +1 -0
  60. package/src/js/core/TabulatorFull.js +1 -1
  61. package/src/js/core/column/Column.js +6 -0
  62. package/src/js/core/modules/optional.js +2 -1
  63. package/src/js/core/rendering/renderers/BasicVertical.js +4 -2
  64. package/src/js/core/rendering/renderers/VirtualDomHorizontal.js +1 -1
  65. package/src/js/core/row/PseudoRow.js +2 -0
  66. package/src/js/core/tools/Alert.js +4 -0
  67. package/src/js/core/tools/DeprecationAdvisor.js +5 -1
  68. package/src/js/core/tools/Helpers.js +1 -1
  69. package/src/js/core/tools/InteractionMonitor.js +3 -3
  70. package/src/js/modules/Clipboard/Clipboard.js +5 -3
  71. package/src/js/modules/Clipboard/defaults/pasteActions.js +49 -6
  72. package/src/js/modules/Clipboard/defaults/pasteParsers.js +69 -14
  73. package/src/js/modules/ColumnCalcs/ColumnCalcs.js +7 -1
  74. package/src/js/modules/Edit/Edit.js +55 -19
  75. package/src/js/modules/Export/Export.js +38 -18
  76. package/src/js/modules/Format/defaults/formatters/rowSelection.js +2 -2
  77. package/src/js/modules/Format/defaults/formatters/rownum.js +5 -1
  78. package/src/js/modules/FrozenColumns/FrozenColumns.js +10 -11
  79. package/src/js/modules/FrozenRows/FrozenRows.js +6 -1
  80. package/src/js/modules/History/History.js +2 -2
  81. package/src/js/modules/History/defaults/redoers.js +4 -0
  82. package/src/js/modules/History/defaults/undoers.js +4 -0
  83. package/src/js/modules/Keybindings/defaults/actions.js +38 -1
  84. package/src/js/modules/Keybindings/defaults/bindings.js +16 -1
  85. package/src/js/modules/Menu/Menu.js +3 -1
  86. package/src/js/modules/MoveColumns/MoveColumns.js +5 -0
  87. package/src/js/modules/Popup/Popup.js +1 -1
  88. package/src/js/modules/ResizeTable/ResizeTable.js +3 -3
  89. package/src/js/modules/SelectRange/Range.js +347 -0
  90. package/src/js/modules/SelectRange/RangeComponent.js +93 -0
  91. package/src/js/modules/SelectRange/SelectRange.js +855 -0
  92. package/src/js/modules/SelectRow/SelectRow.js +46 -26
  93. package/src/js/modules/Sort/Sort.js +111 -105
  94. package/src/js/modules/Validate/defaults/validators.js +11 -0
  95. package/src/scss/tabulator.scss +95 -13
  96. package/src/scss/themes/bulma/tabulator_bulma.scss +7 -0
  97. package/src/scss/themes/materialize/tabulator_materialize.scss +7 -1
  98. package/src/scss/themes/tabulator_midnight.scss +13 -0
  99. package/src/scss/themes/tabulator_modern.scss +9 -0
  100. package/src/scss/themes/tabulator_site.scss +13 -2
@@ -0,0 +1,855 @@
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");
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 - 2);
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 + 1].getValue(),
520
+ isLeftOfStartingCellEmpty = cells[colPos] ? !cells[colPos].getValue() : false,
521
+ jumpCol = colPos,
522
+ nextCell = this.findJumpCell(cells.slice(0, colPos), true, isStartingCellEmpty, isLeftOfStartingCellEmpty);
523
+
524
+ if(nextCell){
525
+ jumpCol = nextCell.column.getPosition() - 2;
526
+ }
527
+
528
+ return jumpCol;
529
+ }
530
+
531
+ findJumpCellRight(rowPos, colPos){
532
+ var row = this.getRowByRangePos(rowPos),
533
+ cells = row.cells.filter((cell) => cell.column.visible),
534
+ isStartingCellEmpty = !cells[colPos + 1].getValue(),
535
+ isRightOfStartingCellEmpty = cells[colPos + 2] ? !cells[colPos + 2].getValue() : false,
536
+ jumpCol = colPos,
537
+ nextCell = this.findJumpCell(cells.slice(colPos + 2, cells.length), false, isStartingCellEmpty, isRightOfStartingCellEmpty);
538
+
539
+ if(nextCell){
540
+ jumpCol = nextCell.column.getPosition() - 2;
541
+ }
542
+
543
+ return jumpCol;
544
+ }
545
+
546
+ findJumpCellUp(rowPos, colPos) {
547
+ var column = this.getColumnByRangePos(colPos),
548
+ cells = column.cells.filter((cell) => this.table.rowManager.activeRows.includes(cell.row)),
549
+ isStartingCellEmpty = !cells[rowPos].getValue(),
550
+ isTopOfStartingCellEmpty = cells[rowPos - 1] ? !cells[rowPos - 1].getValue() : false,
551
+ jumpRow = rowPos,
552
+ nextCell = this.findJumpCell(cells.slice(0, jumpRow), true, isStartingCellEmpty, isTopOfStartingCellEmpty);
553
+
554
+ if(nextCell){
555
+ jumpRow = nextCell.row.position - 1;
556
+ }
557
+
558
+ return jumpRow;
559
+ }
560
+
561
+ findJumpCellDown(rowPos, colPos) {
562
+ var column = this.getColumnByRangePos(colPos),
563
+ cells = column.cells.filter((cell) => this.table.rowManager.activeRows.includes(cell.row)),
564
+ isStartingCellEmpty = !cells[rowPos].getValue(),
565
+ isBottomOfStartingCellEmpty = cells[rowPos + 1] ? !cells[rowPos + 1].getValue() : false,
566
+ jumpRow = rowPos,
567
+ nextCell = this.findJumpCell(cells.slice(jumpRow + 1, cells.length), false, isStartingCellEmpty, isBottomOfStartingCellEmpty);
568
+
569
+ if(nextCell){
570
+ jumpRow = nextCell.row.position - 1;
571
+ }
572
+
573
+ return jumpRow;
574
+ }
575
+
576
+ ///////////////////////////////////
577
+ /////// Selection ///////
578
+ ///////////////////////////////////
579
+ newSelection(event, element) {
580
+ var range;
581
+
582
+ if (element.type === "column") {
583
+ if(!this.columnSelection){
584
+ return;
585
+ }
586
+
587
+ if (element === this.rowHeader) {
588
+ range = this.resetRanges();
589
+ this.selecting = "all";
590
+
591
+ const topLeftCell = this.getCell(0, 0);
592
+ const bottomRightCell = this.getCell(-1, -1);
593
+
594
+ range.setBounds(topLeftCell, bottomRightCell);
595
+ return;
596
+ } else {
597
+ this.selecting = "column";
598
+ }
599
+ } else if (element.column === this.rowHeader) {
600
+ this.selecting = "row";
601
+ } else {
602
+ this.selecting = "cell";
603
+ }
604
+
605
+ if (event.shiftKey) {
606
+ this.activeRange.setBounds(false, element);
607
+ } else if (event.ctrlKey) {
608
+ this.addRange().setBounds(element);
609
+ } else {
610
+ this.resetRanges().setBounds(element);
611
+ }
612
+ }
613
+
614
+ autoScroll(range, row, column) {
615
+ var tableHolder = this.table.rowManager.element,
616
+ rowHeader = this.rowHeader.getElement(),
617
+ rect, view, withinHorizontalView, withinVerticalView;
618
+
619
+ if (typeof row === 'undefined') {
620
+ row = this.getRowByRangePos(range.end.row).getElement();
621
+ }
622
+
623
+ if (typeof column === 'undefined') {
624
+ column = this.getColumnByRangePos(range.end.col).getElement();
625
+ }
626
+
627
+ rect = {
628
+ left: column.offsetLeft,
629
+ right: column.offsetLeft + column.offsetWidth,
630
+ top: row.offsetTop,
631
+ bottom: row.offsetTop + row.offsetHeight,
632
+ };
633
+
634
+ view = {
635
+ left: tableHolder.scrollLeft + rowHeader.offsetWidth,
636
+ right: Math.ceil(tableHolder.scrollLeft + tableHolder.clientWidth),
637
+ top: tableHolder.scrollTop,
638
+ bottom: tableHolder.scrollTop + tableHolder.offsetHeight - this.table.rowManager.scrollbarWidth,
639
+ };
640
+
641
+ withinHorizontalView = view.left < rect.left && rect.left < view.right && view.left < rect.right && rect.right < view.right;
642
+
643
+ withinVerticalView = view.top < rect.top && rect.top < view.bottom && view.top < rect.bottom && rect.bottom < view.bottom;
644
+
645
+ if (!withinHorizontalView) {
646
+ if (rect.left < view.left) {
647
+ tableHolder.scrollLeft = rect.left - rowHeader.offsetWidth;
648
+ } else if (rect.right > view.right) {
649
+ tableHolder.scrollLeft = rect.right - tableHolder.clientWidth;
650
+ }
651
+ }
652
+
653
+ if (!withinVerticalView) {
654
+ if (rect.top < view.top) {
655
+ tableHolder.scrollTop = rect.top;
656
+ } else if (rect.bottom > view.bottom) {
657
+ tableHolder.scrollTop = rect.bottom - tableHolder.clientHeight;
658
+ }
659
+ }
660
+ }
661
+
662
+
663
+ ///////////////////////////////////
664
+ /////// Layout ///////
665
+ ///////////////////////////////////
666
+
667
+ layoutChange(){
668
+ this.overlay.style.visibility = "hidden";
669
+ clearTimeout(this.layoutChangeTimeout);
670
+ this.layoutChangeTimeout = setTimeout(this.layoutRanges.bind(this), 200);
671
+ }
672
+
673
+ redraw(force) {
674
+ if (force) {
675
+ this.selecting = 'cell';
676
+ this.resetRanges();
677
+ this.layoutElement();
678
+ }
679
+ }
680
+
681
+ layoutElement(visibleRows) {
682
+ var rows;
683
+
684
+ if (visibleRows) {
685
+ rows = this.table.rowManager.getVisibleRows(true);
686
+ } else {
687
+ rows = this.table.rowManager.getRows();
688
+ }
689
+
690
+ rows.forEach((row) => {
691
+ if (row.type === "row") {
692
+ this.layoutRow(row);
693
+ row.cells.forEach((cell) => this.renderCell(cell));
694
+ }
695
+ });
696
+
697
+ this.getTableColumns().forEach((column) => {
698
+ this.layoutColumn(column);
699
+ });
700
+
701
+ this.layoutRanges();
702
+ }
703
+
704
+ layoutRow(row) {
705
+ var el = row.getElement(),
706
+ selected = false,
707
+ occupied = this.ranges.some((range) => range.occupiesRow(row));
708
+
709
+ if (this.selecting === "row") {
710
+ selected = occupied;
711
+ } else if (this.selecting === "all") {
712
+ selected = true;
713
+ }
714
+
715
+ el.classList.toggle("tabulator-range-selected", selected);
716
+ el.classList.toggle("tabulator-range-highlight", occupied);
717
+ }
718
+
719
+ layoutColumn(column) {
720
+ var el = column.getElement(),
721
+ selected = false,
722
+ occupied = this.ranges.some((range) => range.occupiesColumn(column));
723
+
724
+ if (this.selecting === "column") {
725
+ selected = occupied;
726
+ } else if (this.selecting === "all") {
727
+ selected = true;
728
+ }
729
+
730
+ el.classList.toggle("tabulator-range-selected", selected);
731
+ el.classList.toggle("tabulator-range-highlight", occupied);
732
+ }
733
+
734
+ layoutRanges() {
735
+ var activeCell;
736
+
737
+ if (!this.table.initialized) {
738
+ return;
739
+ }
740
+
741
+ activeCell = this.getActiveCell();
742
+
743
+ if (!activeCell) {
744
+ return;
745
+ }
746
+
747
+ this.activeRangeCellElement.style.left = activeCell.row.getElement().offsetLeft + activeCell.getElement().offsetLeft + "px";
748
+ this.activeRangeCellElement.style.top = activeCell.row.getElement().offsetTop + "px";
749
+ this.activeRangeCellElement.style.width = activeCell.getElement().offsetLeft + activeCell.getElement().offsetWidth - activeCell.getElement().offsetLeft + "px";
750
+ this.activeRangeCellElement.style.height = activeCell.row.getElement().offsetTop + activeCell.row.getElement().offsetHeight - activeCell.row.getElement().offsetTop + "px";
751
+
752
+ this.ranges.forEach((range) => range.layout());
753
+
754
+ this.overlay.style.visibility = "visible";
755
+ }
756
+
757
+
758
+ ///////////////////////////////////
759
+ /////// Helper Functions ///////
760
+ ///////////////////////////////////
761
+
762
+ getCell(rowIdx, colIdx) {
763
+ var row;
764
+
765
+ if (colIdx < 0) {
766
+ colIdx = this.getTableColumns().length + colIdx - 1;
767
+
768
+ if (colIdx < 0) {
769
+ return null;
770
+ }
771
+ }
772
+
773
+ if (rowIdx < 0) {
774
+ rowIdx = this.getTableRows().length + rowIdx;
775
+ }
776
+
777
+ row = this.table.rowManager.getRowFromPosition(rowIdx + 1);
778
+
779
+ return row ? row.getCells(false, true).filter((cell) => cell.column.visible)[colIdx + 1] : null;
780
+ }
781
+
782
+
783
+ getActiveCell() {
784
+ return this.getCell(this.activeRange.start.row, this.activeRange.start.col);
785
+ }
786
+
787
+ getRowByRangePos(pos) {
788
+ return this.getTableRows()[pos];
789
+ }
790
+
791
+ getColumnByRangePos(pos) {
792
+ return this.getTableColumns()[pos + 1];
793
+ }
794
+
795
+ getTableRows() {
796
+ return this.table.rowManager.getDisplayRows();
797
+ }
798
+
799
+ getTableColumns() {
800
+ return this.table.columnManager.getVisibleColumnsByIndex();
801
+ }
802
+
803
+ addRange(start, end) {
804
+ var range;
805
+
806
+ if(this.maxRanges !== true && this.ranges.length >= this.maxRanges){
807
+ this.ranges.shift().destroy();
808
+ }
809
+
810
+ range = new Range(this.table, this, start, end);
811
+
812
+ this.activeRange = range;
813
+ this.ranges.push(range);
814
+ this.rangeContainer.appendChild(range.element);
815
+
816
+ return range;
817
+ }
818
+
819
+ resetRanges() {
820
+ var range, cell;
821
+
822
+ this.ranges.forEach((range) => range.destroy());
823
+ this.ranges = [];
824
+
825
+ range = this.addRange();
826
+
827
+ if(this.table.rowManager.activeRows.length){
828
+ cell = this.table.rowManager.activeRows[0].cells[this.rowHeader ? 1 : 0];
829
+
830
+ if(cell){
831
+ range.setBounds(cell);
832
+ this.initializeFocus(cell);
833
+ }
834
+ }
835
+
836
+ return range;
837
+ }
838
+
839
+ tableDestroyed(){
840
+ document.removeEventListener("mouseup", this.mouseUpEvent);
841
+ this.table.rowManager.element.removeEventListener("keydown", this.keyDownEvent);
842
+ }
843
+
844
+ selectedRows(component) {
845
+ return component ? this.activeRange.getRows().map((row) => row.getComponent()) : this.activeRange.getRows();
846
+ }
847
+
848
+ selectedColumns(component) {
849
+ return component ? this.activeRange.getColumns().map((col) => col.getComponent()) : this.activeRange.getColumns();
850
+ }
851
+ }
852
+
853
+ SelectRange.moduleName = "selectRange";
854
+
855
+ export default SelectRange;