tabulator-tables 5.5.4 → 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 (99) 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 +1830 -244
  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 +1900 -312
  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 +9 -1
  58. package/src/js/core/Tabulator.js +1 -0
  59. package/src/js/core/TabulatorFull.js +1 -1
  60. package/src/js/core/column/Column.js +6 -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 +55 -19
  74. package/src/js/modules/Export/Export.js +38 -18
  75. package/src/js/modules/Format/defaults/formatters/rowSelection.js +2 -2
  76. package/src/js/modules/Format/defaults/formatters/rownum.js +5 -1
  77. package/src/js/modules/FrozenColumns/FrozenColumns.js +10 -11
  78. package/src/js/modules/FrozenRows/FrozenRows.js +6 -1
  79. package/src/js/modules/History/History.js +2 -2
  80. package/src/js/modules/History/defaults/redoers.js +4 -0
  81. package/src/js/modules/History/defaults/undoers.js +4 -0
  82. package/src/js/modules/Keybindings/defaults/actions.js +38 -1
  83. package/src/js/modules/Keybindings/defaults/bindings.js +16 -1
  84. package/src/js/modules/Menu/Menu.js +3 -1
  85. package/src/js/modules/MoveColumns/MoveColumns.js +5 -0
  86. package/src/js/modules/Popup/Popup.js +1 -1
  87. package/src/js/modules/ResizeTable/ResizeTable.js +3 -3
  88. package/src/js/modules/SelectRange/Range.js +347 -0
  89. package/src/js/modules/SelectRange/RangeComponent.js +93 -0
  90. package/src/js/modules/SelectRange/SelectRange.js +855 -0
  91. package/src/js/modules/SelectRow/SelectRow.js +46 -26
  92. package/src/js/modules/Sort/Sort.js +111 -105
  93. package/src/js/modules/Validate/defaults/validators.js +11 -0
  94. package/src/scss/tabulator.scss +95 -13
  95. package/src/scss/themes/bulma/tabulator_bulma.scss +7 -0
  96. package/src/scss/themes/materialize/tabulator_materialize.scss +7 -1
  97. package/src/scss/themes/tabulator_midnight.scss +13 -0
  98. package/src/scss/themes/tabulator_modern.scss +9 -0
  99. package/src/scss/themes/tabulator_site.scss +13 -2
@@ -1,4 +1,4 @@
1
- /* Tabulator v5.5.4 (c) Oliver Folkerd 2024 */
1
+ /* Tabulator v5.6.0 (c) Oliver Folkerd 2024 */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
4
4
  typeof define === 'function' && define.amd ? define(factory) :
@@ -191,8 +191,8 @@
191
191
  /////////// Deprecation Checks ///////////
192
192
  //////////////////////////////////////////
193
193
 
194
- deprecationCheck(oldOption, newOption){
195
- return this.table.deprecationAdvisor.check(oldOption, newOption);
194
+ deprecationCheck(oldOption, newOption, convert){
195
+ return this.table.deprecationAdvisor.check(oldOption, newOption, convert);
196
196
  }
197
197
 
198
198
  deprecationCheckMsg(oldOption, msg){
@@ -1553,6 +1553,8 @@
1553
1553
 
1554
1554
  this.table.columnManager.rerenderColumns(true);
1555
1555
 
1556
+ this.dispatch("column-deleted", this);
1557
+
1556
1558
  resolve();
1557
1559
  });
1558
1560
  }
@@ -1693,6 +1695,10 @@
1693
1695
 
1694
1696
  return this.component;
1695
1697
  }
1698
+
1699
+ getPosition(){
1700
+ return this.table.columnManager.getVisibleColumnsByIndex().indexOf(this) + 1;
1701
+ }
1696
1702
  }
1697
1703
 
1698
1704
  Column.defaultOptionList = defaultColumnOptions;
@@ -3018,6 +3024,10 @@
3018
3024
 
3019
3025
  return index > -1 ? this.columnsByIndex[index] : false;
3020
3026
  }
3027
+
3028
+ getVisibleColumnsByIndex() {
3029
+ return this.columnsByIndex.filter((col) => col.visible);
3030
+ }
3021
3031
 
3022
3032
  getColumns(){
3023
3033
  return this.columns;
@@ -3972,8 +3982,6 @@
3972
3982
  }
3973
3983
  });
3974
3984
 
3975
-
3976
-
3977
3985
  if(onlyGroupHeaders){
3978
3986
  element.style.minWidth = this.table.columnManager.getWidth() + "px";
3979
3987
  }else {
@@ -3990,6 +3998,10 @@
3990
3998
  }
3991
3999
 
3992
4000
  this.renderRows();
4001
+
4002
+ if(!this.rows().length){
4003
+ this.table.rowManager.tableEmpty();
4004
+ }
3993
4005
  }
3994
4006
 
3995
4007
  scrollToRowNearestTop(row){
@@ -4983,7 +4995,7 @@
4983
4995
 
4984
4996
  this.regenerateRowPositions();
4985
4997
 
4986
- if(rows.length){
4998
+ if(this.displayRowsCount){
4987
4999
  this._clearPlaceholder();
4988
5000
  }
4989
5001
 
@@ -5612,6 +5624,14 @@
5612
5624
  this.renderEmptyScroll();
5613
5625
  this._showPlaceholder();
5614
5626
  }
5627
+
5628
+ checkPlaceholder(){
5629
+ if(this.displayRowsCount){
5630
+ this._clearPlaceholder();
5631
+ }else {
5632
+ this.tableEmpty();
5633
+ }
5634
+ }
5615
5635
 
5616
5636
  _showPlaceholder(){
5617
5637
  if(this.placeholder){
@@ -6093,11 +6113,11 @@
6093
6113
  }
6094
6114
  }
6095
6115
  }
6096
-
6116
+
6097
6117
  if(targets.group && targets.group === targets.row){
6098
6118
  delete targets.row;
6099
6119
  }
6100
-
6120
+
6101
6121
  return targets;
6102
6122
  }
6103
6123
 
@@ -6629,7 +6649,7 @@
6629
6649
  }
6630
6650
  }
6631
6651
 
6632
- check(oldOption, newOption){
6652
+ check(oldOption, newOption, convert){
6633
6653
  var msg = "";
6634
6654
 
6635
6655
  if(typeof this.options(oldOption) !== "undefined"){
@@ -6638,6 +6658,10 @@
6638
6658
  if(newOption){
6639
6659
  msg = msg + ", Please use the %c" + newOption + "%c option instead";
6640
6660
  this._warnUser(msg, 'font-weight: bold;', 'font-weight: normal;', 'font-weight: bold;', 'font-weight: normal;');
6661
+
6662
+ if(convert){
6663
+ this.table.options[newOption] = this.table.options[oldOption];
6664
+ }
6641
6665
  }else {
6642
6666
  this._warnUser(msg, 'font-weight: bold;', 'font-weight: normal;');
6643
6667
  }
@@ -7867,6 +7891,8 @@
7867
7891
  alert(content, type = "msg"){
7868
7892
  if(content){
7869
7893
  this.clear();
7894
+
7895
+ this.dispatch("alert-show", type);
7870
7896
 
7871
7897
  this.type = type;
7872
7898
 
@@ -7889,6 +7915,8 @@
7889
7915
  }
7890
7916
 
7891
7917
  clear(){
7918
+ this.dispatch("alert-hide", this.type);
7919
+
7892
7920
  if(this.element.parentNode){
7893
7921
  this.element.parentNode.removeChild(this.element);
7894
7922
  }
@@ -8152,6 +8180,7 @@
8152
8180
 
8153
8181
  _loadInitialData(){
8154
8182
  this.dataLoader.load(this.options.data);
8183
+ this.columnManager.verticalAlignHeaders();
8155
8184
  }
8156
8185
 
8157
8186
  //deconstructor
@@ -9199,15 +9228,58 @@
9199
9228
  Ajax.contentTypeFormatters = defaultContentTypeFormatters;
9200
9229
 
9201
9230
  var defaultPasteActions = {
9202
- replace:function(rows){
9203
- return this.table.setData(rows);
9231
+ replace:function(data){
9232
+ return this.table.setData(data);
9204
9233
  },
9205
- update:function(rows){
9206
- return this.table.updateOrAddData(rows);
9234
+ update:function(data){
9235
+ return this.table.updateOrAddData(data);
9207
9236
  },
9208
- insert:function(rows){
9209
- return this.table.addData(rows);
9237
+ insert:function(data){
9238
+ return this.table.addData(data);
9210
9239
  },
9240
+ range:function(data){
9241
+ var rows = [],
9242
+ range = this.table.modules.selectRange.activeRange,
9243
+ singleCell = false,
9244
+ bounds, startCell, startRow, rowWidth, dataLength;
9245
+
9246
+ dataLength = data.length;
9247
+
9248
+ if(range){
9249
+ bounds = range.getBounds();
9250
+ startCell = bounds.start;
9251
+
9252
+ if(bounds.start === bounds.end){
9253
+ singleCell = true;
9254
+ }
9255
+
9256
+ if(startCell){
9257
+ rows = this.table.rowManager.activeRows.slice();
9258
+ startRow = rows.indexOf(startCell.row);
9259
+
9260
+ if(singleCell){
9261
+ rowWidth = data.length;
9262
+ }else {
9263
+ rowWidth = (rows.indexOf(bounds.end.row) - startRow) + 1;
9264
+ }
9265
+
9266
+
9267
+ if(startRow >-1){
9268
+ this.table.blockRedraw();
9269
+
9270
+ rows = rows.slice(startRow, startRow + rowWidth);
9271
+
9272
+ rows.forEach((row, i) => {
9273
+ row.updateData(data[i % dataLength]);
9274
+ });
9275
+
9276
+ this.table.restoreRedraw();
9277
+ }
9278
+ }
9279
+ }
9280
+
9281
+ return rows;
9282
+ }
9211
9283
  };
9212
9284
 
9213
9285
  var defaultPasteParsers = {
@@ -9217,72 +9289,127 @@
9217
9289
  columns = this.table.columnManager.columns,
9218
9290
  columnMap = [],
9219
9291
  rows = [];
9220
-
9292
+
9221
9293
  //get data from clipboard into array of columns and rows.
9222
9294
  clipboard = clipboard.split("\n");
9223
-
9295
+
9224
9296
  clipboard.forEach(function(row){
9225
9297
  data.push(row.split("\t"));
9226
9298
  });
9227
-
9299
+
9228
9300
  if(data.length && !(data.length === 1 && data[0].length < 2)){
9229
-
9301
+
9230
9302
  //check if headers are present by title
9231
9303
  data[0].forEach(function(value){
9232
9304
  var column = columns.find(function(column){
9233
9305
  return value && column.definition.title && value.trim() && column.definition.title.trim() === value.trim();
9234
9306
  });
9235
-
9307
+
9236
9308
  if(column){
9237
9309
  columnMap.push(column);
9238
9310
  }else {
9239
9311
  headerFindSuccess = false;
9240
9312
  }
9241
9313
  });
9242
-
9314
+
9243
9315
  //check if column headers are present by field
9244
9316
  if(!headerFindSuccess){
9245
9317
  headerFindSuccess = true;
9246
9318
  columnMap = [];
9247
-
9319
+
9248
9320
  data[0].forEach(function(value){
9249
9321
  var column = columns.find(function(column){
9250
9322
  return value && column.field && value.trim() && column.field.trim() === value.trim();
9251
9323
  });
9252
-
9324
+
9253
9325
  if(column){
9254
9326
  columnMap.push(column);
9255
9327
  }else {
9256
9328
  headerFindSuccess = false;
9257
9329
  }
9258
9330
  });
9259
-
9331
+
9260
9332
  if(!headerFindSuccess){
9261
9333
  columnMap = this.table.columnManager.columnsByIndex;
9262
9334
  }
9263
9335
  }
9264
-
9336
+
9265
9337
  //remove header row if found
9266
9338
  if(headerFindSuccess){
9267
9339
  data.shift();
9268
9340
  }
9269
-
9341
+
9270
9342
  data.forEach(function(item){
9271
9343
  var row = {};
9272
-
9344
+
9273
9345
  item.forEach(function(value, i){
9274
9346
  if(columnMap[i]){
9275
9347
  row[columnMap[i].field] = value;
9276
9348
  }
9277
9349
  });
9278
-
9350
+
9279
9351
  rows.push(row);
9280
9352
  });
9281
-
9353
+
9282
9354
  return rows;
9283
9355
  }else {
9284
9356
  return false;
9285
9357
  }
9358
+ },
9359
+ range:function(clipboard){
9360
+ var data = [],
9361
+ rows = [],
9362
+ range = this.table.modules.selectRange.activeRange,
9363
+ singleCell = false,
9364
+ bounds, startCell, colWidth, columnMap, startCol;
9365
+
9366
+ if(range){
9367
+ bounds = range.getBounds();
9368
+ startCell = bounds.start;
9369
+
9370
+ if(bounds.start === bounds.end){
9371
+ singleCell = true;
9372
+ }
9373
+
9374
+ if(startCell){
9375
+ //get data from clipboard into array of columns and rows.
9376
+ clipboard = clipboard.split("\n");
9377
+
9378
+ clipboard.forEach(function(row){
9379
+ data.push(row.split("\t"));
9380
+ });
9381
+
9382
+ if(data.length){
9383
+ columnMap = this.table.columnManager.getVisibleColumnsByIndex();
9384
+ startCol = columnMap.indexOf(startCell.column);
9385
+
9386
+ if(startCol > -1){
9387
+ if(singleCell){
9388
+ colWidth = data[0].length;
9389
+ }else {
9390
+ colWidth = (columnMap.indexOf(bounds.end.column) - startCol) + 1;
9391
+ }
9392
+
9393
+ columnMap = columnMap.slice(startCol, startCol + colWidth);
9394
+
9395
+ data.forEach((item) => {
9396
+ var row = {};
9397
+ var itemLength = item.length;
9398
+
9399
+ columnMap.forEach(function(col, i){
9400
+ row[col.field] = item[i % itemLength];
9401
+ });
9402
+
9403
+ rows.push(row);
9404
+ });
9405
+
9406
+ return rows;
9407
+ }
9408
+ }
9409
+ }
9410
+ }
9411
+
9412
+ return false;
9286
9413
  }
9287
9414
  };
9288
9415
 
@@ -9425,6 +9552,7 @@
9425
9552
  var sel, textRange;
9426
9553
  this.blocked = false;
9427
9554
  this.customSelection = false;
9555
+
9428
9556
 
9429
9557
  if (this.mode === true || this.mode === "copy") {
9430
9558
 
@@ -9492,7 +9620,7 @@
9492
9620
  paste(e){
9493
9621
  var data, rowData, rows;
9494
9622
 
9495
- if(this.checkPaseOrigin(e)){
9623
+ if(this.checkPasteOrigin(e)){
9496
9624
 
9497
9625
  data = this.getPasteData(e);
9498
9626
 
@@ -9529,10 +9657,11 @@
9529
9657
  }
9530
9658
 
9531
9659
 
9532
- checkPaseOrigin(e){
9660
+ checkPasteOrigin(e){
9533
9661
  var valid = true;
9662
+ var blocked = this.confirm("clipboard-paste", [e]);
9534
9663
 
9535
- if(e.target.tagName != "DIV" || this.table.modules.edit.currentCell){
9664
+ if(blocked || !["DIV", "SPAN"].includes(e.target.tagName)){
9536
9665
  valid = false;
9537
9666
  }
9538
9667
 
@@ -9967,8 +10096,14 @@
9967
10096
  }
9968
10097
 
9969
10098
  initializeTopRow(){
10099
+ var fragment = document.createDocumentFragment();
10100
+
9970
10101
  if(!this.topInitialized){
9971
- this.table.columnManager.getContentsElement().insertBefore(this.topElement, this.table.columnManager.headersElement.nextSibling);
10102
+
10103
+ fragment.appendChild(document.createElement("br"));
10104
+ fragment.appendChild(this.topElement);
10105
+
10106
+ this.table.columnManager.getContentsElement().insertBefore(fragment, this.table.columnManager.headersElement.nextSibling);
9972
10107
  this.topInitialized = true;
9973
10108
  }
9974
10109
  }
@@ -13710,6 +13845,8 @@
13710
13845
  this.registerColumnOption("cellEdited");
13711
13846
  this.registerColumnOption("cellEditCancelled");
13712
13847
 
13848
+ this.registerTableOption("editTriggerEvent", "focus");
13849
+
13713
13850
  this.registerTableFunction("getEditedCells", this.getEditedCells.bind(this));
13714
13851
  this.registerTableFunction("clearCellEdited", this.clearCellEdited.bind(this));
13715
13852
  this.registerTableFunction("navigatePrev", this.navigatePrev.bind(this));
@@ -13741,16 +13878,30 @@
13741
13878
  this.subscribe("row-deleting", this.rowDeleteCheck.bind(this));
13742
13879
  this.subscribe("row-layout", this.rowEditableCheck.bind(this));
13743
13880
  this.subscribe("data-refreshing", this.cancelEdit.bind(this));
13881
+ this.subscribe("clipboard-paste", this.pasteBlocker.bind(this));
13744
13882
 
13745
13883
  this.subscribe("keybinding-nav-prev", this.navigatePrev.bind(this, undefined));
13746
13884
  this.subscribe("keybinding-nav-next", this.keybindingNavigateNext.bind(this));
13747
- this.subscribe("keybinding-nav-left", this.navigateLeft.bind(this, undefined));
13748
- this.subscribe("keybinding-nav-right", this.navigateRight.bind(this, undefined));
13885
+
13886
+
13887
+ // this.subscribe("keybinding-nav-left", this.navigateLeft.bind(this, undefined));
13888
+ // this.subscribe("keybinding-nav-right", this.navigateRight.bind(this, undefined));
13749
13889
  this.subscribe("keybinding-nav-up", this.navigateUp.bind(this, undefined));
13750
13890
  this.subscribe("keybinding-nav-down", this.navigateDown.bind(this, undefined));
13751
13891
  }
13752
13892
 
13753
13893
 
13894
+ ///////////////////////////////////
13895
+ ///////// Paste Negation //////////
13896
+ ///////////////////////////////////
13897
+
13898
+ pasteBlocker(e){
13899
+ if(this.currentCell){
13900
+ return true;
13901
+ }
13902
+ }
13903
+
13904
+
13754
13905
  ///////////////////////////////////
13755
13906
  ////// Keybinding Functions ///////
13756
13907
  ///////////////////////////////////
@@ -13758,7 +13909,7 @@
13758
13909
  keybindingNavigateNext(e){
13759
13910
  var cell = this.currentCell,
13760
13911
  newRow = this.options("tabEndNewRow");
13761
-
13912
+
13762
13913
  if(cell){
13763
13914
  if(!this.navigateNext(cell, e)){
13764
13915
  if(newRow){
@@ -14147,12 +14298,6 @@
14147
14298
  this.updateCellClass(cell);
14148
14299
  element.setAttribute("tabindex", 0);
14149
14300
 
14150
- element.addEventListener("click", function(e){
14151
- if(!element.classList.contains("tabulator-editing")){
14152
- element.focus({preventScroll: true});
14153
- }
14154
- });
14155
-
14156
14301
  element.addEventListener("mousedown", function(e){
14157
14302
  if (e.button === 2) {
14158
14303
  e.preventDefault();
@@ -14160,12 +14305,33 @@
14160
14305
  self.mouseClick = true;
14161
14306
  }
14162
14307
  });
14308
+
14309
+ if(this.options("editTriggerEvent") === "dblclick"){
14310
+ element.addEventListener("dblclick", function(e){
14311
+ if(!element.classList.contains("tabulator-editing")){
14312
+ element.focus({preventScroll: true});
14313
+ self.edit(cell, e, false);
14314
+ }
14315
+ });
14316
+ }
14163
14317
 
14164
- element.addEventListener("focus", function(e){
14165
- if(!self.recursionBlock){
14166
- self.edit(cell, e, false);
14167
- }
14168
- });
14318
+
14319
+ if(this.options("editTriggerEvent") === "focus" || this.options("editTriggerEvent") === "click"){
14320
+ element.addEventListener("click", function(e){
14321
+ if(!element.classList.contains("tabulator-editing")){
14322
+ element.focus({preventScroll: true});
14323
+ self.edit(cell, e, false);
14324
+ }
14325
+ });
14326
+ }
14327
+
14328
+ if(this.options("editTriggerEvent") === "focus"){
14329
+ element.addEventListener("focus", function(e){
14330
+ if(!self.recursionBlock){
14331
+ self.edit(cell, e, false);
14332
+ }
14333
+ });
14334
+ }
14169
14335
  }
14170
14336
  }
14171
14337
 
@@ -14312,7 +14478,6 @@
14312
14478
  allowEdit = this.allowEdit(cell);
14313
14479
 
14314
14480
  if(allowEdit || forceEdit){
14315
-
14316
14481
  self.cancelEdit();
14317
14482
 
14318
14483
  self.currentCell = cell;
@@ -14362,27 +14527,33 @@
14362
14527
  }
14363
14528
  }else {
14364
14529
  console.warn("Edit Error - Editor should return an instance of Node, the editor returned:", cellEditor);
14365
- element.blur();
14530
+ this.blur(element);
14366
14531
  return false;
14367
14532
  }
14368
14533
  }else {
14369
- element.blur();
14534
+ this.blur(element);
14370
14535
  return false;
14371
14536
  }
14372
14537
 
14373
14538
  return true;
14374
14539
  }else {
14375
14540
  this.mouseClick = false;
14376
- element.blur();
14541
+ this.blur(element);
14377
14542
  return false;
14378
14543
  }
14379
14544
  }else {
14380
14545
  this.mouseClick = false;
14381
- element.blur();
14546
+ this.blur(element);
14382
14547
  return false;
14383
14548
  }
14384
14549
  }
14385
14550
 
14551
+ blur(element){
14552
+ if(!this.confirm("edit-blur", [element]) ){
14553
+ element.blur();
14554
+ }
14555
+ }
14556
+
14386
14557
  getEditedCells(){
14387
14558
  var output = [];
14388
14559
 
@@ -14466,10 +14637,20 @@
14466
14637
  this.cloneTableStyle = style;
14467
14638
  this.config = config || {};
14468
14639
  this.colVisProp = colVisProp;
14640
+
14641
+ var headers, body;
14469
14642
 
14470
- var headers = this.config.columnHeaders !== false ? this.headersToExportRows(this.generateColumnGroupHeaders()) : [];
14471
- var body = this.bodyToExportRows(this.rowLookup(range));
14472
-
14643
+ if (range === 'range') {
14644
+ var columns = this.table.modules.selectRange.selectedColumns();
14645
+ headers = this.config.columnHeaders !== false
14646
+ ? this.headersToExportRows(this.generateColumnGroupHeaders(columns))
14647
+ : [];
14648
+ body = this.bodyToExportRows(this.rowLookup(range), this.table.modules.selectRange.selectedColumns(true));
14649
+ } else {
14650
+ headers = this.config.columnHeaders !== false ? this.headersToExportRows(this.generateColumnGroupHeaders()) : [];
14651
+ body = this.bodyToExportRows(this.rowLookup(range));
14652
+ }
14653
+
14473
14654
  return headers.concat(body);
14474
14655
  }
14475
14656
 
@@ -14504,7 +14685,11 @@
14504
14685
  case "selected":
14505
14686
  rows = this.table.modules.selectRow.selectedRows;
14506
14687
  break;
14507
-
14688
+
14689
+ case "range":
14690
+ rows = this.table.modules.selectRange.selectedRows();
14691
+ break;
14692
+
14508
14693
  case "active":
14509
14694
  default:
14510
14695
  if(this.table.options.pagination){
@@ -14518,10 +14703,12 @@
14518
14703
  return Object.assign([], rows);
14519
14704
  }
14520
14705
 
14521
- generateColumnGroupHeaders(){
14706
+ generateColumnGroupHeaders(columns){
14522
14707
  var output = [];
14523
14708
 
14524
- var columns = this.config.columnGroups !== false ? this.table.columnManager.columns : this.table.columnManager.columnsByIndex;
14709
+ if (!columns) {
14710
+ columns = this.config.columnGroups !== false ? this.table.columnManager.columns : this.table.columnManager.columnsByIndex;
14711
+ }
14525
14712
 
14526
14713
  columns.forEach((column) => {
14527
14714
  var colData = this.processColumnGroup(column);
@@ -14530,7 +14717,7 @@
14530
14717
  output.push(colData);
14531
14718
  }
14532
14719
  });
14533
-
14720
+
14534
14721
  return output;
14535
14722
  }
14536
14723
 
@@ -14658,16 +14845,16 @@
14658
14845
  return exportRows;
14659
14846
  }
14660
14847
 
14661
- bodyToExportRows(rows){
14662
-
14663
- var columns = [];
14848
+ bodyToExportRows(rows, columns = []){
14664
14849
  var exportRows = [];
14665
14850
 
14666
- this.table.columnManager.columnsByIndex.forEach((column) => {
14667
- if (this.columnVisCheck(column)) {
14668
- columns.push(column.getComponent());
14669
- }
14670
- });
14851
+ if (columns.length === 0) {
14852
+ this.table.columnManager.columnsByIndex.forEach((column) => {
14853
+ if (this.columnVisCheck(column)) {
14854
+ columns.push(column.getComponent());
14855
+ }
14856
+ });
14857
+ }
14671
14858
 
14672
14859
  if(this.config.columnCalcs !== false && this.table.modExists("columnCalcs")){
14673
14860
  if(this.table.modules.columnCalcs.topInitialized){
@@ -14678,7 +14865,7 @@
14678
14865
  rows.push(this.table.modules.columnCalcs.botRow);
14679
14866
  }
14680
14867
  }
14681
-
14868
+
14682
14869
  rows = rows.filter((row) => {
14683
14870
  switch(row.type){
14684
14871
  case "group":
@@ -14905,7 +15092,8 @@
14905
15092
  if(col){
14906
15093
  var cellEl = document.createElement("td"),
14907
15094
  column = col.component._column,
14908
- index = this.table.columnManager.findColumnIndex(column),
15095
+ table = this.table,
15096
+ index = table.columnManager.findColumnIndex(column),
14909
15097
  value = col.value,
14910
15098
  cellStyle;
14911
15099
 
@@ -14932,6 +15120,9 @@
14932
15120
  getRow:function(){
14933
15121
  return row.component;
14934
15122
  },
15123
+ getTable:function(){
15124
+ return table;
15125
+ },
14935
15126
  getComponent:function(){
14936
15127
  return cellWrapper;
14937
15128
  },
@@ -16590,8 +16781,12 @@
16590
16781
  function rownum(cell, formatterParams, onRendered){
16591
16782
  var content = document.createElement("span");
16592
16783
  var row = cell.getRow();
16784
+ var table = cell.getTable();
16593
16785
 
16594
16786
  row.watchPosition((position) => {
16787
+ if (formatterParams.relativeToPage) {
16788
+ position += table.modules.page.getPageSize() * (table.modules.page.getPage() - 1);
16789
+ }
16595
16790
  content.innerText = position;
16596
16791
  });
16597
16792
 
@@ -16668,7 +16863,7 @@
16668
16863
  if(row instanceof RowComponent){
16669
16864
 
16670
16865
  checkbox.addEventListener("change", (e) => {
16671
- if(this.table.options.selectableRangeMode === "click"){
16866
+ if(this.table.options.selectableRowsRangeMode === "click"){
16672
16867
  if(!blocked){
16673
16868
  row.toggleSelect();
16674
16869
  }else {
@@ -16679,7 +16874,7 @@
16679
16874
  }
16680
16875
  });
16681
16876
 
16682
- if(this.table.options.selectableRangeMode === "click"){
16877
+ if(this.table.options.selectableRowsRangeMode === "click"){
16683
16878
  checkbox.addEventListener("click", (e) => {
16684
16879
  blocked = true;
16685
16880
  this.table.modules.selectRow.handleComplexRowClick(row._row, e);
@@ -16972,7 +17167,9 @@
16972
17167
  this.subscribe("columns-loading", this.reset.bind(this));
16973
17168
 
16974
17169
  this.subscribe("column-add", this.reinitializeColumns.bind(this));
16975
- this.subscribe("column-delete", this.reinitializeColumns.bind(this));
17170
+ this.subscribe("column-deleted", this.reinitializeColumns.bind(this));
17171
+ this.subscribe("column-hide", this.reinitializeColumns.bind(this));
17172
+ this.subscribe("column-show", this.reinitializeColumns.bind(this));
16976
17173
 
16977
17174
  this.subscribe("table-redraw", this.layout.bind(this));
16978
17175
  this.subscribe("layout-refreshing", this.blockLayout.bind(this));
@@ -16998,16 +17195,16 @@
16998
17195
  this.table.columnManager.columnsByIndex.forEach((column) => {
16999
17196
  this.initializeColumn(column);
17000
17197
  });
17198
+
17199
+ this.layout();
17001
17200
  }
17002
17201
 
17003
17202
  //initialize specific column
17004
17203
  initializeColumn(column){
17005
17204
  var config = {margin:0, edge:false};
17006
17205
 
17007
- if(!column.isGroup){
17008
-
17206
+ if(!column.isGroup){
17009
17207
  if(this.frozenCheck(column)){
17010
-
17011
17208
  config.position = this.initializationMode;
17012
17209
 
17013
17210
  if(this.initializationMode == "left"){
@@ -17098,9 +17295,8 @@
17098
17295
  leftParents.push(parentEl);
17099
17296
  }
17100
17297
 
17101
- if(column.modules.frozen.edge){
17102
- parentEl.classList.add("tabulator-frozen-" + column.modules.frozen.position);
17103
- }
17298
+ parentEl.classList.toggle("tabulator-frozen-left", column.modules.frozen.edge && column.modules.frozen.position === "left");
17299
+ parentEl.classList.toggle("tabulator-frozen-right", column.modules.frozen.edge && column.modules.frozen.position === "right");
17104
17300
  }else {
17105
17301
  this.layoutElement(column.getElement(), column);
17106
17302
  }
@@ -17148,7 +17344,6 @@
17148
17344
  //layout columns appropriately
17149
17345
  layout(){
17150
17346
  if(this.active && !this.blocked){
17151
-
17152
17347
  //calculate left columns
17153
17348
  this.layoutColumnPosition();
17154
17349
 
@@ -17211,9 +17406,8 @@
17211
17406
 
17212
17407
  element.classList.add("tabulator-frozen");
17213
17408
 
17214
- if(column.modules.frozen.edge){
17215
- element.classList.add("tabulator-frozen-" + column.modules.frozen.position);
17216
- }
17409
+ element.classList.toggle("tabulator-frozen-left", column.modules.frozen.edge && column.modules.frozen.position === "left");
17410
+ element.classList.toggle("tabulator-frozen-right", column.modules.frozen.edge && column.modules.frozen.position === "right");
17217
17411
  }
17218
17412
  }
17219
17413
 
@@ -17257,12 +17451,17 @@
17257
17451
  }
17258
17452
 
17259
17453
  initialize(){
17454
+ var fragment = document.createDocumentFragment();
17455
+
17260
17456
  this.rows = [];
17261
17457
 
17262
17458
  this.topElement.classList.add("tabulator-frozen-rows-holder");
17459
+
17460
+ fragment.appendChild(document.createElement("br"));
17461
+ fragment.appendChild(this.topElement);
17263
17462
 
17264
17463
  // this.table.columnManager.element.append(this.topElement);
17265
- this.table.columnManager.getContentsElement().insertBefore(this.topElement, this.table.columnManager.headersElement.nextSibling);
17464
+ this.table.columnManager.getContentsElement().insertBefore(fragment, this.table.columnManager.headersElement.nextSibling);
17266
17465
 
17267
17466
  this.subscribe("row-deleting", this.detachRow.bind(this));
17268
17467
  this.subscribe("rows-visible", this.visibleRows.bind(this));
@@ -18728,6 +18927,8 @@
18728
18927
 
18729
18928
  rowAdd: function(action){
18730
18929
  action.component.deleteActual();
18930
+
18931
+ this.table.rowManager.checkPlaceholder();
18731
18932
  },
18732
18933
 
18733
18934
  rowDelete: function(action){
@@ -18738,6 +18939,8 @@
18738
18939
  }
18739
18940
 
18740
18941
  this._rebindRow(action.component, newRow);
18942
+
18943
+ this.table.rowManager.checkPlaceholder();
18741
18944
  },
18742
18945
 
18743
18946
  rowMove: function(action){
@@ -18764,10 +18967,14 @@
18764
18967
  }
18765
18968
 
18766
18969
  this._rebindRow(action.component, newRow);
18970
+
18971
+ this.table.rowManager.checkPlaceholder();
18767
18972
  },
18768
18973
 
18769
18974
  rowDelete:function(action){
18770
18975
  action.component.deleteActual();
18976
+
18977
+ this.table.rowManager.checkPlaceholder();
18771
18978
  },
18772
18979
 
18773
18980
  rowMove: function(action){
@@ -18892,7 +19099,7 @@
18892
19099
 
18893
19100
  return true;
18894
19101
  }else {
18895
- console.warn("History Undo Error - No more history to undo");
19102
+ console.warn(this.options("history") ? "History Undo Error - No more history to undo" : "History module not enabled");
18896
19103
  return false;
18897
19104
  }
18898
19105
  }
@@ -18910,7 +19117,7 @@
18910
19117
 
18911
19118
  return true;
18912
19119
  }else {
18913
- console.warn("History Redo Error - No more history to redo");
19120
+ console.warn(this.options("history") ? "History Redo Error - No more history to redo" : "History module not enabled");
18914
19121
  return false;
18915
19122
  }
18916
19123
  }
@@ -19727,6 +19934,8 @@
19727
19934
  navNext:9,
19728
19935
  navUp:38,
19729
19936
  navDown:40,
19937
+ navLeft:37,
19938
+ navRight:39,
19730
19939
  scrollPageUp:33,
19731
19940
  scrollPageDown:34,
19732
19941
  scrollToStart:36,
@@ -19734,6 +19943,19 @@
19734
19943
  undo:["ctrl + 90", "meta + 90"],
19735
19944
  redo:["ctrl + 89", "meta + 89"],
19736
19945
  copyToClipboard:["ctrl + 67", "meta + 67"],
19946
+
19947
+ rangeJumpUp:["ctrl + 38", "meta + 38"],
19948
+ rangeJumpDown:["ctrl + 40", "meta + 40"],
19949
+ rangeJumpLeft:["ctrl + 37", "meta + 37"],
19950
+ rangeJumpRight:["ctrl + 39", "meta + 39"],
19951
+ rangeExpandUp:"shift + 38",
19952
+ rangeExpandDown:"shift + 40",
19953
+ rangeExpandLeft:"shift + 37",
19954
+ rangeExpandRight:"shift + 39",
19955
+ rangeExpandJumpUp:["ctrl + shift + 38", "meta + shift + 38"],
19956
+ rangeExpandJumpDown:["ctrl + shift + 40", "meta + shift + 40"],
19957
+ rangeExpandJumpLeft:["ctrl + shift + 37", "meta + shift + 37"],
19958
+ rangeExpandJumpRight:["ctrl + shift + 39", "meta + shift + 39"],
19737
19959
  };
19738
19960
 
19739
19961
  var defaultActions = {
@@ -19821,6 +20043,43 @@
19821
20043
  this.dispatch("keybinding-nav-down", e);
19822
20044
  },
19823
20045
 
20046
+ rangeJumpLeft: function(e){
20047
+ this.dispatch("keybinding-nav-range", e, "left", true, false);
20048
+ },
20049
+ rangeJumpRight: function(e){
20050
+ this.dispatch("keybinding-nav-range", e, "right", true, false);
20051
+ },
20052
+ rangeJumpUp: function(e){
20053
+ this.dispatch("keybinding-nav-range", e, "up", true, false);
20054
+ },
20055
+ rangeJumpDown: function(e){
20056
+ this.dispatch("keybinding-nav-range", e, "down", true, false);
20057
+ },
20058
+ rangeExpandLeft: function(e){
20059
+ this.dispatch("keybinding-nav-range", e, "left", false, true);
20060
+ },
20061
+ rangeExpandRight: function(e){
20062
+ this.dispatch("keybinding-nav-range", e, "right", false, true);
20063
+ },
20064
+ rangeExpandUp: function(e){
20065
+ this.dispatch("keybinding-nav-range", e, "up", false, true);
20066
+ },
20067
+ rangeExpandDown: function(e){
20068
+ this.dispatch("keybinding-nav-range", e, "down", false, true);
20069
+ },
20070
+ rangeExpandJumpLeft: function(e){
20071
+ this.dispatch("keybinding-nav-range", e, "left", true, true);
20072
+ },
20073
+ rangeExpandJumpRight: function(e){
20074
+ this.dispatch("keybinding-nav-range", e, "right", true, true);
20075
+ },
20076
+ rangeExpandJumpUp: function(e){
20077
+ this.dispatch("keybinding-nav-range", e, "up", true, true);
20078
+ },
20079
+ rangeExpandJumpDown: function(e){
20080
+ this.dispatch("keybinding-nav-range", e, "down", true, true);
20081
+ },
20082
+
19824
20083
  undo:function(e){
19825
20084
  var cell = false;
19826
20085
  if(this.table.options.history && this.table.modExists("history") && this.table.modExists("edit")){
@@ -20099,7 +20358,7 @@
20099
20358
  this.subscribe("group-dblclick", this.loadMenuEvent.bind(this, this.table.options.groupDblClickMenu));
20100
20359
  }
20101
20360
  }
20102
-
20361
+
20103
20362
  initializeColumn(column){
20104
20363
  var def = column.definition;
20105
20364
 
@@ -20308,6 +20567,7 @@
20308
20567
  this.rootPopup = null;
20309
20568
 
20310
20569
  if(this.currentComponent){
20570
+ this.dispatch("menu-closed", menu, popup);
20311
20571
  this.dispatchExternal("menuClosed", this.currentComponent.getComponent());
20312
20572
  this.currentComponent = null;
20313
20573
  }
@@ -20315,6 +20575,7 @@
20315
20575
 
20316
20576
  this.currentComponent = component;
20317
20577
 
20578
+ this.dispatch("menu-opened", menu, popup);
20318
20579
  this.dispatchExternal("menuOpened", component.getComponent());
20319
20580
  }
20320
20581
  }
@@ -20358,8 +20619,13 @@
20358
20619
  initialize(){
20359
20620
  if(this.table.options.movableColumns){
20360
20621
  this.subscribe("column-init", this.initializeColumn.bind(this));
20622
+ this.subscribe("alert-show", this.abortMove.bind(this));
20361
20623
  }
20362
20624
  }
20625
+
20626
+ abortMove(){
20627
+ clearTimeout(this.checkTimeout);
20628
+ }
20363
20629
 
20364
20630
  initializeColumn(column){
20365
20631
  var self = this,
@@ -22945,7 +23211,7 @@
22945
23211
  this.subscribe("group-dblclick", this.loadPopupEvent.bind(this, this.table.options.groupDblClickPopup));
22946
23212
  }
22947
23213
  }
22948
-
23214
+
22949
23215
  initializeColumn(column){
22950
23216
  var def = column.definition;
22951
23217
 
@@ -24102,7 +24368,7 @@
24102
24368
  this.autoResize = true;
24103
24369
 
24104
24370
  this.resizeObserver = new ResizeObserver((entry) => {
24105
- if(!table.browserMobile || (table.browserMobile &&!table.modules.edit.currentCell)){
24371
+ if(!table.browserMobile || (table.browserMobile && (!table.modules.edit || (table.modules.edit && !table.modules.edit.currentCell)))){
24106
24372
 
24107
24373
  var nodeHeight = Math.floor(entry[0].contentRect.height);
24108
24374
  var nodeWidth = Math.floor(entry[0].contentRect.width);
@@ -24128,7 +24394,7 @@
24128
24394
  if(this.table.element.parentNode && !this.table.rowManager.fixedHeight && (tableStyle.getPropertyValue("max-height") || tableStyle.getPropertyValue("min-height"))){
24129
24395
 
24130
24396
  this.containerObserver = new ResizeObserver((entry) => {
24131
- if(!table.browserMobile || (table.browserMobile &&!table.modules.edit.currentCell)){
24397
+ if(!table.browserMobile || (table.browserMobile && (!table.modules.edit || (table.modules.edit && !table.modules.edit.currentCell)))){
24132
24398
 
24133
24399
  var nodeHeight = Math.floor(entry[0].contentRect.height);
24134
24400
  var nodeWidth = Math.floor(entry[0].contentRect.width);
@@ -24151,7 +24417,7 @@
24151
24417
 
24152
24418
  }else {
24153
24419
  this.binding = function(){
24154
- if(!table.browserMobile || (table.browserMobile && !table.modules.edit.currentCell)){
24420
+ if(!table.browserMobile || (table.browserMobile && (!table.modules.edit || (table.modules.edit && !table.modules.edit.currentCell)))){
24155
24421
  table.columnManager.rerenderColumns(true);
24156
24422
  table.redraw();
24157
24423
  }
@@ -24570,11 +24836,11 @@
24570
24836
  this.selectedRows = []; //hold selected rows
24571
24837
  this.headerCheckboxElement = null; // hold header select element
24572
24838
 
24573
- this.registerTableOption("selectable", "highlight"); //highlight rows on hover
24574
- this.registerTableOption("selectableRangeMode", "drag"); //highlight rows on hover
24575
- this.registerTableOption("selectableRollingSelection", true); //roll selection once maximum number of selectable rows is reached
24576
- this.registerTableOption("selectablePersistence", true); // maintain selection when table view is updated
24577
- this.registerTableOption("selectableCheck", function(data, row){return true;}); //check whether row is selectable
24839
+ this.registerTableOption("selectableRows", "highlight"); //highlight rows on hover
24840
+ this.registerTableOption("selectableRowsRangeMode", "drag"); //highlight rows on hover
24841
+ this.registerTableOption("selectableRowsRollingSelection", true); //roll selection once maximum number of selectable rows is reached
24842
+ this.registerTableOption("selectableRowsPersistence", true); // maintain selection when table view is updated
24843
+ this.registerTableOption("selectableRowsCheck", function(data, row){return true;}); //check whether row is selectable
24578
24844
 
24579
24845
  this.registerTableFunction("selectRow", this.selectRows.bind(this));
24580
24846
  this.registerTableFunction("deselectRow", this.deselectRows.bind(this));
@@ -24590,17 +24856,32 @@
24590
24856
  }
24591
24857
 
24592
24858
  initialize(){
24593
- if(this.table.options.selectable !== false){
24859
+
24860
+ this.deprecatedOptionsCheck();
24861
+
24862
+ if(this.table.options.selectableRows === "highlight" && this.table.options.selectableRange){
24863
+ this.table.options.selectableRows = false;
24864
+ }
24865
+
24866
+ if(this.table.options.selectableRows !== false){
24594
24867
  this.subscribe("row-init", this.initializeRow.bind(this));
24595
24868
  this.subscribe("row-deleting", this.rowDeleted.bind(this));
24596
24869
  this.subscribe("rows-wipe", this.clearSelectionData.bind(this));
24597
24870
  this.subscribe("rows-retrieve", this.rowRetrieve.bind(this));
24598
24871
 
24599
- if(this.table.options.selectable && !this.table.options.selectablePersistence){
24872
+ if(this.table.options.selectableRows && !this.table.options.selectableRowsPersistence){
24600
24873
  this.subscribe("data-refreshing", this.deselectRows.bind(this));
24601
24874
  }
24602
24875
  }
24603
24876
  }
24877
+
24878
+ deprecatedOptionsCheck(){
24879
+ this.deprecationCheck("selectable", "selectableRows", true);
24880
+ this.deprecationCheck("selectableRollingSelection", "selectableRowsRollingSelection", true);
24881
+ this.deprecationCheck("selectableRangeMode", "selectableRowsRangeMode", true);
24882
+ this.deprecationCheck("selectablePersistence", "selectableRowsPersistence", true);
24883
+ this.deprecationCheck("selectableCheck", "selectableRowsCheck", true);
24884
+ }
24604
24885
 
24605
24886
  rowRetrieve(type, prevValue){
24606
24887
  return type === "selected" ? this.selectedRows : prevValue;
@@ -24625,6 +24906,7 @@
24625
24906
 
24626
24907
  initializeRow(row){
24627
24908
  var self = this,
24909
+ selectable = self.checkRowSelectability(row),
24628
24910
  element = row.getElement();
24629
24911
 
24630
24912
  // trigger end of row selection
@@ -24638,14 +24920,14 @@
24638
24920
  };
24639
24921
 
24640
24922
  row.modules.select = {selected:false};
24923
+
24924
+ element.classList.toggle("tabulator-selectable", selectable);
24925
+ element.classList.toggle("tabulator-unselectable", !selectable);
24641
24926
 
24642
24927
  //set row selection class
24643
- if(self.checkRowSelectability(row)){
24644
- element.classList.add("tabulator-selectable");
24645
- element.classList.remove("tabulator-unselectable");
24646
-
24647
- if(self.table.options.selectable && self.table.options.selectable != "highlight"){
24648
- if(self.table.options.selectableRangeMode === "click"){
24928
+ if(self.checkRowSelectability(row)){
24929
+ if(self.table.options.selectableRows && self.table.options.selectableRows != "highlight"){
24930
+ if(self.table.options.selectableRowsRangeMode === "click"){
24649
24931
  element.addEventListener("click", this.handleComplexRowClick.bind(this, row));
24650
24932
  }else {
24651
24933
  element.addEventListener("click", function(e){
@@ -24694,10 +24976,6 @@
24694
24976
  });
24695
24977
  }
24696
24978
  }
24697
-
24698
- }else {
24699
- element.classList.add("tabulator-unselectable");
24700
- element.classList.remove("tabulator-selectable");
24701
24979
  }
24702
24980
  }
24703
24981
 
@@ -24719,8 +24997,8 @@
24719
24997
  toggledRows.forEach((toggledRow)=>{
24720
24998
  if(toggledRow !== this.lastClickedRow){
24721
24999
 
24722
- if(this.table.options.selectable !== true && !this.isRowSelected(row)){
24723
- if(this.selectedRows.length < this.table.options.selectable){
25000
+ if(this.table.options.selectableRows !== true && !this.isRowSelected(row)){
25001
+ if(this.selectedRows.length < this.table.options.selectableRows){
24724
25002
  this.toggleRow(toggledRow);
24725
25003
  }
24726
25004
  }else {
@@ -24732,9 +25010,9 @@
24732
25010
  }else {
24733
25011
  this.deselectRows(undefined, true);
24734
25012
 
24735
- if(this.table.options.selectable !== true){
24736
- if(toggledRows.length > this.table.options.selectable){
24737
- toggledRows = toggledRows.slice(0, this.table.options.selectable);
25013
+ if(this.table.options.selectableRows !== true){
25014
+ if(toggledRows.length > this.table.options.selectableRows){
25015
+ toggledRows = toggledRows.slice(0, this.table.options.selectableRows);
24738
25016
  }
24739
25017
  }
24740
25018
 
@@ -24754,7 +25032,7 @@
24754
25032
 
24755
25033
  checkRowSelectability(row){
24756
25034
  if(row && row.type === "row"){
24757
- return this.table.options.selectableCheck.call(this.table, row.getComponent());
25035
+ return this.table.options.selectableRowsCheck.call(this.table, row.getComponent());
24758
25036
  }
24759
25037
 
24760
25038
  return false;
@@ -24781,6 +25059,10 @@
24781
25059
  rowMatch = this.table.rowManager.rows;
24782
25060
  break;
24783
25061
 
25062
+ case "number":
25063
+ rowMatch = this.table.rowManager.findRow(rows);
25064
+ break;
25065
+
24784
25066
  case "string":
24785
25067
  rowMatch = this.table.rowManager.findRow(rows);
24786
25068
 
@@ -24816,9 +25098,9 @@
24816
25098
  //select an individual row
24817
25099
  _selectRow(rowInfo, silent, force){
24818
25100
  //handle max row count
24819
- if(!isNaN(this.table.options.selectable) && this.table.options.selectable !== true && !force){
24820
- if(this.selectedRows.length >= this.table.options.selectable){
24821
- if(this.table.options.selectableRollingSelection){
25101
+ if(!isNaN(this.table.options.selectableRows) && this.table.options.selectableRows !== true && !force){
25102
+ if(this.selectedRows.length >= this.table.options.selectableRows){
25103
+ if(this.table.options.selectableRowsRollingSelection){
24822
25104
  this._deselectRow(this.selectedRows[0]);
24823
25105
  }else {
24824
25106
  return false;
@@ -24872,6 +25154,10 @@
24872
25154
  case "undefined":
24873
25155
  rowMatch = Object.assign([], this.selectedRows);
24874
25156
  break;
25157
+
25158
+ case "number":
25159
+ rowMatch = this.table.rowManager.findRow(rows);
25160
+ break;
24875
25161
 
24876
25162
  case "string":
24877
25163
  rowMatch = this.table.rowManager.findRow(rows);
@@ -25299,90 +25585,90 @@
25299
25585
  };
25300
25586
 
25301
25587
  class Sort extends Module{
25302
-
25588
+
25303
25589
  constructor(table){
25304
25590
  super(table);
25305
-
25591
+
25306
25592
  this.sortList = []; //holder current sort
25307
25593
  this.changed = false; //has the sort changed since last render
25308
-
25594
+
25309
25595
  this.registerTableOption("sortMode", "local"); //local or remote sorting
25310
-
25596
+
25311
25597
  this.registerTableOption("initialSort", false); //initial sorting criteria
25312
25598
  this.registerTableOption("columnHeaderSortMulti", true); //multiple or single column sorting
25313
25599
  this.registerTableOption("sortOrderReverse", false); //reverse internal sort ordering
25314
25600
  this.registerTableOption("headerSortElement", "<div class='tabulator-arrow'></div>"); //header sort element
25315
25601
  this.registerTableOption("headerSortClickElement", "header"); //element which triggers sort when clicked
25316
-
25602
+
25317
25603
  this.registerColumnOption("sorter");
25318
25604
  this.registerColumnOption("sorterParams");
25319
-
25605
+
25320
25606
  this.registerColumnOption("headerSort", true);
25321
25607
  this.registerColumnOption("headerSortStartingDir");
25322
25608
  this.registerColumnOption("headerSortTristate");
25323
-
25609
+
25324
25610
  }
25325
-
25611
+
25326
25612
  initialize(){
25327
25613
  this.subscribe("column-layout", this.initializeColumn.bind(this));
25328
25614
  this.subscribe("table-built", this.tableBuilt.bind(this));
25329
25615
  this.registerDataHandler(this.sort.bind(this), 20);
25330
-
25616
+
25331
25617
  this.registerTableFunction("setSort", this.userSetSort.bind(this));
25332
25618
  this.registerTableFunction("getSorters", this.getSort.bind(this));
25333
25619
  this.registerTableFunction("clearSort", this.clearSort.bind(this));
25334
-
25620
+
25335
25621
  if(this.table.options.sortMode === "remote"){
25336
25622
  this.subscribe("data-params", this.remoteSortParams.bind(this));
25337
25623
  }
25338
25624
  }
25339
-
25625
+
25340
25626
  tableBuilt(){
25341
25627
  if(this.table.options.initialSort){
25342
25628
  this.setSort(this.table.options.initialSort);
25343
25629
  }
25344
25630
  }
25345
-
25631
+
25346
25632
  remoteSortParams(data, config, silent, params){
25347
25633
  var sorters = this.getSort();
25348
-
25634
+
25349
25635
  sorters.forEach((item) => {
25350
25636
  delete item.column;
25351
25637
  });
25352
-
25638
+
25353
25639
  params.sort = sorters;
25354
-
25640
+
25355
25641
  return params;
25356
25642
  }
25357
-
25358
-
25643
+
25644
+
25359
25645
  ///////////////////////////////////
25360
25646
  ///////// Table Functions /////////
25361
25647
  ///////////////////////////////////
25362
-
25648
+
25363
25649
  userSetSort(sortList, dir){
25364
25650
  this.setSort(sortList, dir);
25365
25651
  // this.table.rowManager.sorterRefresh();
25366
25652
  this.refreshSort();
25367
25653
  }
25368
-
25654
+
25369
25655
  clearSort(){
25370
25656
  this.clear();
25371
25657
  // this.table.rowManager.sorterRefresh();
25372
25658
  this.refreshSort();
25373
25659
  }
25374
-
25375
-
25660
+
25661
+
25376
25662
  ///////////////////////////////////
25377
25663
  ///////// Internal Logic //////////
25378
25664
  ///////////////////////////////////
25379
-
25665
+
25380
25666
  //initialize column header for sorting
25381
25667
  initializeColumn(column){
25382
25668
  var sorter = false,
25383
25669
  colEl,
25384
25670
  arrowEl;
25385
-
25671
+
25386
25672
  switch(typeof column.definition.sorter){
25387
25673
  case "string":
25388
25674
  if(Sort.sorters[column.definition.sorter]){
@@ -25391,28 +25677,28 @@
25391
25677
  console.warn("Sort Error - No such sorter found: ", column.definition.sorter);
25392
25678
  }
25393
25679
  break;
25394
-
25680
+
25395
25681
  case "function":
25396
25682
  sorter = column.definition.sorter;
25397
25683
  break;
25398
25684
  }
25399
-
25685
+
25400
25686
  column.modules.sort = {
25401
25687
  sorter:sorter, dir:"none",
25402
25688
  params:column.definition.sorterParams || {},
25403
25689
  startingDir:column.definition.headerSortStartingDir || "asc",
25404
25690
  tristate: column.definition.headerSortTristate,
25405
25691
  };
25406
-
25692
+
25407
25693
  if(column.definition.headerSort !== false){
25408
-
25694
+
25409
25695
  colEl = column.getElement();
25410
-
25696
+
25411
25697
  colEl.classList.add("tabulator-sortable");
25412
-
25698
+
25413
25699
  arrowEl = document.createElement("div");
25414
25700
  arrowEl.classList.add("tabulator-col-sorter");
25415
-
25701
+
25416
25702
  switch(this.table.options.headerSortClickElement){
25417
25703
  case "icon":
25418
25704
  arrowEl.classList.add("tabulator-col-sorter-element");
@@ -25424,33 +25710,39 @@
25424
25710
  colEl.classList.add("tabulator-col-sorter-element");
25425
25711
  break;
25426
25712
  }
25427
-
25713
+
25428
25714
  switch(this.table.options.headerSortElement){
25429
25715
  case "function":
25430
- //do nothing
25716
+ //do nothing
25431
25717
  break;
25432
-
25718
+
25433
25719
  case "object":
25434
25720
  arrowEl.appendChild(this.table.options.headerSortElement);
25435
25721
  break;
25436
-
25722
+
25437
25723
  default:
25438
25724
  arrowEl.innerHTML = this.table.options.headerSortElement;
25439
25725
  }
25440
-
25726
+
25441
25727
  //create sorter arrow
25442
25728
  column.titleHolderElement.appendChild(arrowEl);
25443
-
25729
+
25444
25730
  column.modules.sort.element = arrowEl;
25445
-
25731
+
25446
25732
  this.setColumnHeaderSortIcon(column, "none");
25447
-
25733
+
25734
+ if(this.table.options.headerSortClickElement === "icon"){
25735
+ arrowEl.addEventListener("mousedown", (e) => {
25736
+ e.stopPropagation();
25737
+ });
25738
+ }
25739
+
25448
25740
  //sort on click
25449
25741
  (this.table.options.headerSortClickElement === "icon" ? arrowEl : colEl).addEventListener("click", (e) => {
25450
25742
  var dir = "",
25451
25743
  sorters=[],
25452
25744
  match = false;
25453
-
25745
+
25454
25746
  if(column.modules.sort){
25455
25747
  if(column.modules.sort.tristate){
25456
25748
  if(column.modules.sort.dir == "none"){
@@ -25467,26 +25759,26 @@
25467
25759
  case "asc":
25468
25760
  dir = "desc";
25469
25761
  break;
25470
-
25762
+
25471
25763
  case "desc":
25472
25764
  dir = "asc";
25473
25765
  break;
25474
-
25766
+
25475
25767
  default:
25476
25768
  dir = column.modules.sort.startingDir;
25477
25769
  }
25478
25770
  }
25479
-
25771
+
25480
25772
  if (this.table.options.columnHeaderSortMulti && (e.shiftKey || e.ctrlKey)) {
25481
25773
  sorters = this.getSort();
25482
-
25774
+
25483
25775
  match = sorters.findIndex((sorter) => {
25484
25776
  return sorter.field === column.getField();
25485
25777
  });
25486
-
25778
+
25487
25779
  if(match > -1){
25488
25780
  sorters[match].dir = dir;
25489
-
25781
+
25490
25782
  match = sorters.splice(match, 1)[0];
25491
25783
  if(dir != "none"){
25492
25784
  sorters.push(match);
@@ -25496,7 +25788,7 @@
25496
25788
  sorters.push({column:column, dir:dir});
25497
25789
  }
25498
25790
  }
25499
-
25791
+
25500
25792
  //add to existing sort
25501
25793
  this.setSort(sorters);
25502
25794
  }else {
@@ -25506,63 +25798,63 @@
25506
25798
  //sort by column only
25507
25799
  this.setSort(column, dir);
25508
25800
  }
25509
-
25801
+
25510
25802
  }
25511
-
25803
+
25512
25804
  // this.table.rowManager.sorterRefresh(!this.sortList.length);
25513
25805
  this.refreshSort();
25514
25806
  }
25515
25807
  });
25516
25808
  }
25517
25809
  }
25518
-
25810
+
25519
25811
  refreshSort(){
25520
25812
  if(this.table.options.sortMode === "remote"){
25521
25813
  this.reloadData(null, false, false);
25522
25814
  }else {
25523
25815
  this.refreshData(true);
25524
25816
  }
25525
-
25817
+
25526
25818
  //TODO - Persist left position of row manager
25527
25819
  // left = this.scrollLeft;
25528
25820
  // this.scrollHorizontal(left);
25529
25821
  }
25530
-
25822
+
25531
25823
  //check if the sorters have changed since last use
25532
25824
  hasChanged(){
25533
25825
  var changed = this.changed;
25534
25826
  this.changed = false;
25535
25827
  return changed;
25536
25828
  }
25537
-
25829
+
25538
25830
  //return current sorters
25539
25831
  getSort(){
25540
25832
  var self = this,
25541
25833
  sorters = [];
25542
-
25834
+
25543
25835
  self.sortList.forEach(function(item){
25544
25836
  if(item.column){
25545
25837
  sorters.push({column:item.column.getComponent(), field:item.column.getField(), dir:item.dir});
25546
25838
  }
25547
25839
  });
25548
-
25840
+
25549
25841
  return sorters;
25550
25842
  }
25551
-
25843
+
25552
25844
  //change sort list and trigger sort
25553
25845
  setSort(sortList, dir){
25554
25846
  var self = this,
25555
25847
  newSortList = [];
25556
-
25848
+
25557
25849
  if(!Array.isArray(sortList)){
25558
25850
  sortList = [{column: sortList, dir:dir}];
25559
25851
  }
25560
-
25852
+
25561
25853
  sortList.forEach(function(item){
25562
25854
  var column;
25563
-
25855
+
25564
25856
  column = self.table.columnManager.findColumn(item.column);
25565
-
25857
+
25566
25858
  if(column){
25567
25859
  item.column = column;
25568
25860
  newSortList.push(item);
@@ -25570,42 +25862,42 @@
25570
25862
  }else {
25571
25863
  console.warn("Sort Warning - Sort field does not exist and is being ignored: ", item.column);
25572
25864
  }
25573
-
25865
+
25574
25866
  });
25575
-
25867
+
25576
25868
  self.sortList = newSortList;
25577
-
25869
+
25578
25870
  this.dispatch("sort-changed");
25579
25871
  }
25580
-
25872
+
25581
25873
  //clear sorters
25582
25874
  clear(){
25583
25875
  this.setSort([]);
25584
25876
  }
25585
-
25877
+
25586
25878
  //find appropriate sorter for column
25587
25879
  findSorter(column){
25588
25880
  var row = this.table.rowManager.activeRows[0],
25589
25881
  sorter = "string",
25590
25882
  field, value;
25591
-
25883
+
25592
25884
  if(row){
25593
25885
  row = row.getData();
25594
25886
  field = column.getField();
25595
-
25887
+
25596
25888
  if(field){
25597
-
25889
+
25598
25890
  value = column.getFieldValue(row);
25599
-
25891
+
25600
25892
  switch(typeof value){
25601
25893
  case "undefined":
25602
25894
  sorter = "string";
25603
25895
  break;
25604
-
25896
+
25605
25897
  case "boolean":
25606
25898
  sorter = "boolean";
25607
25899
  break;
25608
-
25900
+
25609
25901
  default:
25610
25902
  if(!isNaN(value) && value !== ""){
25611
25903
  sorter = "number";
@@ -25618,70 +25910,70 @@
25618
25910
  }
25619
25911
  }
25620
25912
  }
25621
-
25913
+
25622
25914
  return Sort.sorters[sorter];
25623
25915
  }
25624
-
25916
+
25625
25917
  //work through sort list sorting data
25626
25918
  sort(data){
25627
25919
  var self = this,
25628
25920
  sortList = this.table.options.sortOrderReverse ? self.sortList.slice().reverse() : self.sortList,
25629
25921
  sortListActual = [],
25630
25922
  rowComponents = [];
25631
-
25923
+
25632
25924
  if(this.subscribedExternal("dataSorting")){
25633
25925
  this.dispatchExternal("dataSorting", self.getSort());
25634
25926
  }
25635
-
25927
+
25636
25928
  self.clearColumnHeaders();
25637
-
25929
+
25638
25930
  if(this.table.options.sortMode !== "remote"){
25639
-
25931
+
25640
25932
  //build list of valid sorters and trigger column specific callbacks before sort begins
25641
25933
  sortList.forEach(function(item, i){
25642
25934
  var sortObj;
25643
-
25935
+
25644
25936
  if(item.column){
25645
25937
  sortObj = item.column.modules.sort;
25646
-
25938
+
25647
25939
  if(sortObj){
25648
-
25940
+
25649
25941
  //if no sorter has been defined, take a guess
25650
25942
  if(!sortObj.sorter){
25651
25943
  sortObj.sorter = self.findSorter(item.column);
25652
25944
  }
25653
-
25945
+
25654
25946
  item.params = typeof sortObj.params === "function" ? sortObj.params(item.column.getComponent(), item.dir) : sortObj.params;
25655
-
25947
+
25656
25948
  sortListActual.push(item);
25657
25949
  }
25658
-
25950
+
25659
25951
  self.setColumnHeader(item.column, item.dir);
25660
25952
  }
25661
25953
  });
25662
-
25954
+
25663
25955
  //sort data
25664
25956
  if (sortListActual.length) {
25665
25957
  self._sortItems(data, sortListActual);
25666
25958
  }
25667
-
25959
+
25668
25960
  }else {
25669
25961
  sortList.forEach(function(item, i){
25670
25962
  self.setColumnHeader(item.column, item.dir);
25671
25963
  });
25672
25964
  }
25673
-
25965
+
25674
25966
  if(this.subscribedExternal("dataSorted")){
25675
25967
  data.forEach((row) => {
25676
25968
  rowComponents.push(row.getComponent());
25677
25969
  });
25678
-
25970
+
25679
25971
  this.dispatchExternal("dataSorted", self.getSort(), rowComponents);
25680
25972
  }
25681
-
25973
+
25682
25974
  return data;
25683
25975
  }
25684
-
25976
+
25685
25977
  //clear sort arrows on columns
25686
25978
  clearColumnHeaders(){
25687
25979
  this.table.columnManager.getRealColumns().forEach((column) => {
@@ -25692,21 +25984,21 @@
25692
25984
  }
25693
25985
  });
25694
25986
  }
25695
-
25987
+
25696
25988
  //set the column header sort direction
25697
25989
  setColumnHeader(column, dir){
25698
25990
  column.modules.sort.dir = dir;
25699
25991
  column.getElement().setAttribute("aria-sort", dir === "asc" ? "ascending" : "descending");
25700
25992
  this.setColumnHeaderSortIcon(column, dir);
25701
25993
  }
25702
-
25994
+
25703
25995
  setColumnHeaderSortIcon(column, dir){
25704
25996
  var sortEl = column.modules.sort.element,
25705
25997
  arrowEl;
25706
-
25998
+
25707
25999
  if(column.definition.headerSort && typeof this.table.options.headerSortElement === "function"){
25708
26000
  while(sortEl.firstChild) sortEl.removeChild(sortEl.firstChild);
25709
-
26001
+
25710
26002
  arrowEl = this.table.options.headerSortElement.call(this.table, column.getComponent(), dir);
25711
26003
 
25712
26004
  if(typeof arrowEl === "object"){
@@ -25716,45 +26008,45 @@
25716
26008
  }
25717
26009
  }
25718
26010
  }
25719
-
26011
+
25720
26012
  //sort each item in sort list
25721
26013
  _sortItems(data, sortList){
25722
26014
  var sorterCount = sortList.length - 1;
25723
-
26015
+
25724
26016
  data.sort((a, b) => {
25725
26017
  var result;
25726
-
26018
+
25727
26019
  for(var i = sorterCount; i>= 0; i--){
25728
26020
  let sortItem = sortList[i];
25729
-
26021
+
25730
26022
  result = this._sortRow(a, b, sortItem.column, sortItem.dir, sortItem.params);
25731
-
26023
+
25732
26024
  if(result !== 0){
25733
26025
  break;
25734
26026
  }
25735
26027
  }
25736
-
26028
+
25737
26029
  return result;
25738
26030
  });
25739
26031
  }
25740
-
26032
+
25741
26033
  //process individual rows for a sort function on active data
25742
26034
  _sortRow(a, b, column, dir, params){
25743
26035
  var el1Comp, el2Comp;
25744
-
26036
+
25745
26037
  //switch elements depending on search direction
25746
26038
  var el1 = dir == "asc" ? a : b;
25747
26039
  var el2 = dir == "asc" ? b : a;
25748
-
26040
+
25749
26041
  a = column.getFieldValue(el1.getData());
25750
26042
  b = column.getFieldValue(el2.getData());
25751
-
26043
+
25752
26044
  a = typeof a !== "undefined" ? a : "";
25753
26045
  b = typeof b !== "undefined" ? b : "";
25754
-
26046
+
25755
26047
  el1Comp = el1.getComponent();
25756
26048
  el2Comp = el2.getComponent();
25757
-
26049
+
25758
26050
  return column.modules.sort.sorter.call(this, a, b, el1Comp, el2Comp, column.getComponent(), dir, params);
25759
26051
  }
25760
26052
  }
@@ -25764,44 +26056,1326 @@
25764
26056
  //load defaults
25765
26057
  Sort.sorters = defaultSorters;
25766
26058
 
25767
- class Tooltip extends Module{
26059
+ class RangeComponent {
26060
+ constructor(range) {
26061
+ this._range = range;
26062
+
26063
+ return new Proxy(this, {
26064
+ get: function (target, name, receiver) {
26065
+ if (typeof target[name] !== "undefined") {
26066
+ return target[name];
26067
+ } else {
26068
+ return target._range.table.componentFunctionBinder.handle("range", target._range, name);
26069
+ }
26070
+ },
26071
+ });
26072
+ }
26073
+
26074
+ getElement() {
26075
+ return this._range.element;
26076
+ }
26077
+
26078
+ getData() {
26079
+ return this._range.getData();
26080
+ }
26081
+
26082
+ getCells() {
26083
+ return this._range.getCells(true);
26084
+ }
26085
+
26086
+ getStructuredCells() {
26087
+ return this._range.getStructuredCells();
26088
+ }
26089
+
26090
+ getRows() {
26091
+ return this._range.getRows().map((row) => row.getComponent());
26092
+ }
26093
+
26094
+ getColumns() {
26095
+ return this._range.getColumns().map((column) => column.getComponent());
26096
+ }
25768
26097
 
25769
- constructor(table){
26098
+ getBounds() {
26099
+ return this._range.getBounds();
26100
+ }
26101
+
26102
+ getTopEdge() {
26103
+ return this._range.top;
26104
+ }
26105
+
26106
+ getBottomEdge() {
26107
+ return this._range.bottom;
26108
+ }
26109
+
26110
+ getLeftEdge() {
26111
+ return this._range.left;
26112
+ }
26113
+
26114
+ getRightEdge() {
26115
+ return this._range.right;
26116
+ }
26117
+
26118
+ setBounds(start, end){
26119
+ if(this._range.destroyedGuard("setBounds")){
26120
+ this._range.setBounds(start ? start._cell : start, end ? end._cell : end);
26121
+ }
26122
+ }
26123
+
26124
+ setStartBound(start){
26125
+ if(this._range.destroyedGuard("setStartBound")){
26126
+ this._range.setEndBound(start ? start._cell : start);
26127
+ this._range.rangeManager.layoutElement();
26128
+ }
26129
+ }
26130
+
26131
+ setEndBound(end){
26132
+ if(this._range.destroyedGuard("setEndBound")){
26133
+ this._range.setEndBound(end ? end._cell : end);
26134
+ this._range.rangeManager.layoutElement();
26135
+ }
26136
+ }
26137
+
26138
+ clearValues(){
26139
+ if(this._range.destroyedGuard("clearValues")){
26140
+ this._range.clearValues();
26141
+ }
26142
+ }
26143
+
26144
+ remove(){
26145
+ if(this._range.destroyedGuard("remove")){
26146
+ this._range.destroy(true);
26147
+ }
26148
+ }
26149
+ }
26150
+
26151
+ class Range extends CoreFeature{
26152
+ constructor(table, rangeManager, start, end) {
25770
26153
  super(table);
25771
26154
 
25772
- this.tooltipSubscriber = null,
25773
- this.headerSubscriber = null,
26155
+ this.rangeManager = rangeManager;
26156
+ this.element = null;
26157
+ this.initialized = false;
26158
+ this.initializing = {
26159
+ start:false,
26160
+ end:false,
26161
+ };
26162
+ this.destroyed = false;
25774
26163
 
25775
- this.timeout = null;
25776
- this.popupInstance = null;
26164
+ this.top = 0;
26165
+ this.bottom = 0;
26166
+ this.left = 0;
26167
+ this.right = 0;
25777
26168
 
25778
- this.registerTableOption("tooltipGenerationMode", undefined); //deprecated
25779
- this.registerTableOption("tooltipDelay", 300);
26169
+ this.table = table;
26170
+ this.start = {row:0, col:0};
26171
+ this.end = {row:0, col:0};
25780
26172
 
25781
- this.registerColumnOption("tooltip");
25782
- this.registerColumnOption("headerTooltip");
26173
+ this.initElement();
26174
+
26175
+ setTimeout(() => {
26176
+ this.initBounds(start, end);
26177
+ });
25783
26178
  }
25784
26179
 
25785
- initialize(){
25786
- this.deprecatedOptionsCheck();
26180
+ initElement(){
26181
+ this.element = document.createElement("div");
26182
+ this.element.classList.add("tabulator-range");
26183
+ }
26184
+
26185
+ initBounds(start, end){
26186
+ this._updateMinMax();
25787
26187
 
25788
- this.subscribe("column-init", this.initializeColumn.bind(this));
26188
+ if(start){
26189
+ this.setBounds(start, end || start);
26190
+ }
25789
26191
  }
25790
26192
 
25791
- deprecatedOptionsCheck(){
25792
- this.deprecationCheckMsg("tooltipGenerationMode", "This option is no longer needed as tooltips are always generated on hover now");
25793
- }
26193
+ ///////////////////////////////////
26194
+ /////// Boundary Setup ///////
26195
+ ///////////////////////////////////
25794
26196
 
25795
- initializeColumn(column){
25796
- if(column.definition.headerTooltip && !this.headerSubscriber){
25797
- this.headerSubscriber = true;
26197
+ setStart(row, col) {
26198
+ if(this.start.row !== row || this.start.col !== col){
26199
+ this.start.row = row;
26200
+ this.start.col = col;
25798
26201
 
25799
- this.subscribe("column-mousemove", this.mousemoveCheck.bind(this, "headerTooltip"));
25800
- this.subscribe("column-mouseout", this.mouseoutCheck.bind(this, "headerTooltip"));
26202
+ this.initializing.start = true;
26203
+ this._updateMinMax();
25801
26204
  }
25802
-
25803
- if(column.definition.tooltip && !this.tooltipSubscriber){
25804
- this.tooltipSubscriber = true;
26205
+ }
26206
+
26207
+ setEnd(row, col) {
26208
+ if(this.end.row !== row || this.end.col !== col){
26209
+ this.end.row = row;
26210
+ this.end.col = col;
26211
+
26212
+ this.initializing.end = true;
26213
+ this._updateMinMax();
26214
+ }
26215
+ }
26216
+
26217
+ setBounds(start, end, visibleRows){
26218
+ if(start){
26219
+ this.setStartBound(start);
26220
+ }
26221
+
26222
+ this.setEndBound(end || start);
26223
+ this.rangeManager.layoutElement(visibleRows);
26224
+ }
26225
+
26226
+ setStartBound(element){
26227
+ var row, col;
26228
+
26229
+ if (element.type === "column") {
26230
+ if(this.rangeManager.columnSelection){
26231
+ this.setStart(0, element.getPosition() - 2);
26232
+ }
26233
+ }else {
26234
+ row = element.row.position - 1;
26235
+ col = element.column.getPosition() - 2;
26236
+
26237
+ if (element.column === this.rangeManager.rowHeader) {
26238
+ this.setStart(row, 0);
26239
+ } else {
26240
+ this.setStart(row, col);
26241
+ }
26242
+ }
26243
+ }
26244
+
26245
+ setEndBound(element){
26246
+ var rowsCount = this._getTableRows().length,
26247
+ row, col, isRowHeader;
26248
+
26249
+ if (element.type === "column") {
26250
+ if(this.rangeManager.columnSelection){
26251
+ if (this.rangeManager.selecting === "column") {
26252
+ this.setEnd(rowsCount - 1, element.getPosition() - 2);
26253
+ } else if (this.rangeManager.selecting === "cell") {
26254
+ this.setEnd(0, element.getPosition() - 2);
26255
+ }
26256
+ }
26257
+ }else {
26258
+ row = element.row.position - 1;
26259
+ col = element.column.getPosition() - 2;
26260
+ isRowHeader = element.column === this.rangeManager.rowHeader;
26261
+
26262
+ if (this.rangeManager.selecting === "row") {
26263
+ this.setEnd(row, this._getTableColumns().length - 2);
26264
+ } else if (this.rangeManager.selecting !== "row" && isRowHeader) {
26265
+ this.setEnd(row, 0);
26266
+ } else if (this.rangeManager.selecting === "column") {
26267
+ this.setEnd(rowsCount - 1, col);
26268
+ } else {
26269
+ this.setEnd(row, col);
26270
+ }
26271
+ }
26272
+ }
26273
+
26274
+ _updateMinMax() {
26275
+ this.top = Math.min(this.start.row, this.end.row);
26276
+ this.bottom = Math.max(this.start.row, this.end.row);
26277
+ this.left = Math.min(this.start.col, this.end.col);
26278
+ this.right = Math.max(this.start.col, this.end.col);
26279
+
26280
+ if(this.initialized){
26281
+ this.dispatchExternal("rangeChanged", this.getComponent());
26282
+ }else {
26283
+ if(this.initializing.start && this.initializing.end){
26284
+ this.initialized = true;
26285
+ this.dispatchExternal("rangeAdded", this.getComponent());
26286
+ }
26287
+ }
26288
+ }
26289
+
26290
+ _getTableColumns() {
26291
+ return this.table.columnManager.getVisibleColumnsByIndex();
26292
+ }
26293
+
26294
+ _getTableRows() {
26295
+ return this.table.rowManager.getDisplayRows();
26296
+ }
26297
+
26298
+ ///////////////////////////////////
26299
+ /////// Rendering ///////
26300
+ ///////////////////////////////////
26301
+
26302
+ layout() {
26303
+ var _vDomTop = this.table.rowManager.renderer.vDomTop,
26304
+ _vDomBottom = this.table.rowManager.renderer.vDomBottom,
26305
+ _vDomLeft = this.table.columnManager.renderer.leftCol,
26306
+ _vDomRight = this.table.columnManager.renderer.rightCol,
26307
+ top, bottom, left, right, topLeftCell, bottomRightCell;
26308
+
26309
+ if (_vDomTop == null) {
26310
+ _vDomTop = 0;
26311
+ }
26312
+
26313
+ if (_vDomBottom == null) {
26314
+ _vDomBottom = Infinity;
26315
+ }
26316
+
26317
+ if (_vDomLeft == null) {
26318
+ _vDomLeft = 0;
26319
+ }
26320
+
26321
+ if (_vDomRight == null) {
26322
+ _vDomRight = Infinity;
26323
+ }
26324
+
26325
+ if (this.overlaps(_vDomLeft, _vDomTop, _vDomRight, _vDomBottom)) {
26326
+ top = Math.max(this.top, _vDomTop);
26327
+ bottom = Math.min(this.bottom, _vDomBottom);
26328
+ left = Math.max(this.left, _vDomLeft);
26329
+ right = Math.min(this.right, _vDomRight);
26330
+
26331
+ topLeftCell = this.rangeManager.getCell(top, left);
26332
+ bottomRightCell = this.rangeManager.getCell(bottom, right);
26333
+
26334
+ this.element.classList.add("tabulator-range-active");
26335
+ // this.element.classList.toggle("tabulator-range-active", this === this.rangeManager.activeRange);
26336
+
26337
+ this.element.style.left = topLeftCell.row.getElement().offsetLeft + topLeftCell.getElement().offsetLeft + "px";
26338
+ this.element.style.top = topLeftCell.row.getElement().offsetTop + "px";
26339
+ this.element.style.width = bottomRightCell.getElement().offsetLeft + bottomRightCell.getElement().offsetWidth - topLeftCell.getElement().offsetLeft + "px";
26340
+ this.element.style.height = bottomRightCell.row.getElement().offsetTop + bottomRightCell.row.getElement().offsetHeight - topLeftCell.row.getElement().offsetTop + "px";
26341
+ }
26342
+ }
26343
+
26344
+ atTopLeft(cell) {
26345
+ return cell.row.position - 1 === this.top && cell.column.getPosition() - 2 === this.left;
26346
+ }
26347
+
26348
+ atBottomRight(cell) {
26349
+ return cell.row.position - 1 === this.bottom && cell.column.getPosition() - 2 === this.right;
26350
+ }
26351
+
26352
+ occupies(cell) {
26353
+ return this.occupiesRow(cell.row) && this.occupiesColumn(cell.column);
26354
+ }
26355
+
26356
+ occupiesRow(row) {
26357
+ return this.top <= row.position - 1 && row.position - 1 <= this.bottom;
26358
+ }
26359
+
26360
+ occupiesColumn(col) {
26361
+ return this.left <= col.getPosition() - 2 && col.getPosition() - 2 <= this.right;
26362
+ }
26363
+
26364
+ overlaps(left, top, right, bottom) {
26365
+ if ((this.left > right || left > this.right) || (this.top > bottom || top > this.bottom)){
26366
+ return false;
26367
+ }
26368
+
26369
+ return true;
26370
+ }
26371
+
26372
+ getData() {
26373
+ var data = [],
26374
+ rows = this.getRows(),
26375
+ columns = this.getColumns();
26376
+
26377
+ rows.forEach((row) => {
26378
+ var rowData = row.getData(),
26379
+ result = {};
26380
+
26381
+ columns.forEach((column) => {
26382
+ result[column.field] = rowData[column.field];
26383
+ });
26384
+
26385
+ data.push(result);
26386
+ });
26387
+
26388
+ return data;
26389
+ }
26390
+
26391
+ getCells(structured, component) {
26392
+ var cells = [],
26393
+ rows = this.getRows(),
26394
+ columns = this.getColumns();
26395
+
26396
+ if (structured) {
26397
+ cells = rows.map((row) => {
26398
+ var arr = [];
26399
+
26400
+ row.getCells().forEach((cell) => {
26401
+ if (columns.includes(cell.column)) {
26402
+ arr.push(component ? cell.getComponent() : cell);
26403
+ }
26404
+ });
26405
+
26406
+ return arr;
26407
+ });
26408
+ } else {
26409
+ rows.forEach((row) => {
26410
+ row.getCells().forEach((cell) => {
26411
+ if (columns.includes(cell.column)) {
26412
+ cells.push(component ? cell.getComponent() : cell);
26413
+ }
26414
+ });
26415
+ });
26416
+ }
26417
+
26418
+ return cells;
26419
+ }
26420
+
26421
+ getStructuredCells() {
26422
+ return this.getCells(true, true);
26423
+ }
26424
+
26425
+ getRows() {
26426
+ return this._getTableRows().slice(this.top, this.bottom + 1);
26427
+ }
26428
+
26429
+ getColumns() {
26430
+ return this._getTableColumns().slice(this.left + 1, this.right + 2);
26431
+ }
26432
+
26433
+ clearValues(){
26434
+ var cells = this.getCells();
26435
+ var clearValue = this.table.options.selectableRangeClearCellsValue;
26436
+
26437
+ this.table.blockRedraw();
26438
+
26439
+ cells.forEach((cell) => {
26440
+ cell.setValue(clearValue);
26441
+ });
26442
+
26443
+ this.table.restoreRedraw();
26444
+
26445
+ }
26446
+
26447
+ getBounds(component){
26448
+ var cells = this.getCells(false, component),
26449
+ output = {
26450
+ start:null,
26451
+ end:null,
26452
+ };
26453
+
26454
+ if(cells.length){
26455
+ output.start = cells[0];
26456
+ output.end = cells[cells.length - 1];
26457
+ }else {
26458
+ console.warn("No bounds defined on range");
26459
+ }
26460
+
26461
+ return output;
26462
+ }
26463
+
26464
+ getComponent() {
26465
+ if (!this.component) {
26466
+ this.component = new RangeComponent(this);
26467
+ }
26468
+ return this.component;
26469
+ }
26470
+
26471
+ destroy(notify) {
26472
+ this.destroyed = true;
26473
+
26474
+ this.element.remove();
26475
+
26476
+ if(notify){
26477
+ this.rangeManager.rangeRemoved(this);
26478
+ }
26479
+
26480
+ if(this.initialized){
26481
+ this.dispatchExternal("rangeRemoved", this.getComponent());
26482
+ }
26483
+ }
26484
+
26485
+ destroyedGuard(func){
26486
+ if(this.destroyed){
26487
+ console.warn("You cannot call the " + func + " function on a destroyed range");
26488
+ }
26489
+
26490
+ return !this.destroyed;
26491
+ }
26492
+ }
26493
+
26494
+ class SelectRange extends Module {
26495
+ constructor(table) {
26496
+ super(table);
26497
+
26498
+ this.selecting = "cell";
26499
+ this.mousedown = false;
26500
+ this.ranges = [];
26501
+ this.overlay = null;
26502
+ this.rowHeader = null;
26503
+ this.layoutChangeTimeout = null;
26504
+ this.columnSelection = false;
26505
+ this.rowSelection = false;
26506
+ this.maxRanges = 0;
26507
+ this.activeRange = false;
26508
+ this.blockKeydown = false;
26509
+
26510
+ this.keyDownEvent = this._handleKeyDown.bind(this);
26511
+ this.mouseUpEvent = this._handleMouseUp.bind(this);
26512
+
26513
+ this.registerTableOption("selectableRange", false); //enable selectable range
26514
+ this.registerTableOption("selectableRangeColumns", false); //enable selectable range
26515
+ this.registerTableOption("selectableRangeRows", false); //enable selectable range
26516
+ this.registerTableOption("selectableRangeClearCells", false); //allow clearing of active range
26517
+ this.registerTableOption("selectableRangeClearCellsValue", undefined); //value for cleared active range
26518
+
26519
+ this.registerTableFunction("getRangesData", this.getRangesData.bind(this));
26520
+ this.registerTableFunction("getRanges", this.getRanges.bind(this));
26521
+ this.registerTableFunction("addRange", this.addRangeFromComponent.bind(this));
26522
+
26523
+ this.registerComponentFunction("cell", "getRanges", this.cellGetRanges.bind(this));
26524
+ this.registerComponentFunction("row", "getRanges", this.rowGetRanges.bind(this));
26525
+ this.registerComponentFunction("column", "getRanges", this.colGetRanges.bind(this));
26526
+ }
26527
+
26528
+ ///////////////////////////////////
26529
+ /////// Initialization ///////
26530
+ ///////////////////////////////////
26531
+
26532
+ initialize() {
26533
+ if (this.options("selectableRange")) {
26534
+ if(!this.options("selectableRows")){
26535
+
26536
+ this.maxRanges = this.options("selectableRange");
26537
+
26538
+ this.initializeTable();
26539
+ this.initializeWatchers();
26540
+ }else {
26541
+ console.warn("SelectRange functionality cannot be used in conjunction with row selection");
26542
+ }
26543
+ }
26544
+ }
26545
+
26546
+
26547
+ initializeTable() {
26548
+ this.overlay = document.createElement("div");
26549
+ this.overlay.classList.add("tabulator-range-overlay");
26550
+
26551
+ this.rangeContainer = document.createElement("div");
26552
+ this.rangeContainer.classList.add("tabulator-range-container");
26553
+
26554
+ this.activeRangeCellElement = document.createElement("div");
26555
+ this.activeRangeCellElement.classList.add("tabulator-range-cell-active");
26556
+
26557
+ this.overlay.appendChild(this.rangeContainer);
26558
+ this.overlay.appendChild(this.activeRangeCellElement);
26559
+
26560
+ this.table.rowManager.element.addEventListener("keydown", this.keyDownEvent);
26561
+
26562
+ this.resetRanges();
26563
+
26564
+ this.table.rowManager.element.appendChild(this.overlay);
26565
+ this.table.columnManager.element.setAttribute("tabindex", 0);
26566
+ this.table.element.classList.add("tabulator-ranges");
26567
+ }
26568
+
26569
+ initializeWatchers() {
26570
+ this.columnSelection = this.options("selectableRangeColumns");
26571
+ this.rowSelection = this.options("selectableRangeRows");
26572
+
26573
+ this.subscribe("column-init", this.initializeColumn.bind(this));
26574
+ this.subscribe("column-mousedown", this.handleColumnMouseDown.bind(this));
26575
+ this.subscribe("column-mousemove", this.handleColumnMouseMove.bind(this));
26576
+ this.subscribe("column-resized", this.handleColumnResized.bind(this));
26577
+ this.subscribe("column-width", this.layoutChange.bind(this));
26578
+ this.subscribe("column-height", this.layoutChange.bind(this));
26579
+ this.subscribe("column-resized", this.layoutChange.bind(this));
26580
+ this.subscribe("columns-loaded", this.updateHeaderColumn.bind(this));
26581
+
26582
+ this.subscribe("cell-height", this.layoutChange.bind(this));
26583
+ this.subscribe("cell-rendered", this.renderCell.bind(this));
26584
+ this.subscribe("cell-mousedown", this.handleCellMouseDown.bind(this));
26585
+ this.subscribe("cell-mousemove", this.handleCellMouseMove.bind(this));
26586
+ this.subscribe("cell-click", this.handleCellClick.bind(this));
26587
+ this.subscribe("cell-editing", this.handleEditingCell.bind(this));
26588
+
26589
+ this.subscribe("page-changed", this.redraw.bind(this));
26590
+
26591
+ this.subscribe("scroll-vertical", this.layoutChange.bind(this));
26592
+ this.subscribe("scroll-horizontal", this.layoutChange.bind(this));
26593
+
26594
+ this.subscribe("data-destroy", this.tableDestroyed.bind(this));
26595
+ this.subscribe("data-processed", this.resetRanges.bind(this));
26596
+
26597
+ this.subscribe("table-layout", this.layoutElement.bind(this));
26598
+ this.subscribe("table-redraw", this.redraw.bind(this));
26599
+ this.subscribe("table-destroy", this.tableDestroyed.bind(this));
26600
+
26601
+ this.subscribe("edit-editor-clear", this.finishEditingCell.bind(this));
26602
+ this.subscribe("edit-blur", this.restoreFocus.bind(this));
26603
+
26604
+ this.subscribe("keybinding-nav-prev", this.keyNavigate.bind(this, "left"));
26605
+ this.subscribe("keybinding-nav-next", this.keyNavigate.bind(this, "right"));
26606
+ this.subscribe("keybinding-nav-left", this.keyNavigate.bind(this, "left"));
26607
+ this.subscribe("keybinding-nav-right", this.keyNavigate.bind(this, "right"));
26608
+ this.subscribe("keybinding-nav-up", this.keyNavigate.bind(this, "up"));
26609
+ this.subscribe("keybinding-nav-down", this.keyNavigate.bind(this, "down"));
26610
+ this.subscribe("keybinding-nav-range", this.keyNavigateRange.bind(this));
26611
+ }
26612
+
26613
+
26614
+ initializeColumn(column) {
26615
+ if(this.columnSelection && column.definition.headerSort && this.options("headerSortClickElement") !== "icon"){
26616
+ console.warn("Using column headerSort with selectableRangeColumns option may result in unpredictable behavior");
26617
+ }
26618
+
26619
+ if (column.modules.edit) ;
26620
+ }
26621
+
26622
+ updateHeaderColumn(){
26623
+ if(this.rowSelection){
26624
+ this.rowHeader = this.table.columnManager.getVisibleColumnsByIndex()[0];
26625
+
26626
+ if(this.rowHeader){
26627
+ this.rowHeader.definition.cssClass = this.rowHeader.definition.cssClass + " tabulator-range-row-header";
26628
+
26629
+ if(this.rowHeader.definition.headerSort){
26630
+ console.warn("Using column headerSort with selectableRangeRows option may result in unpredictable behavior");
26631
+ }
26632
+
26633
+ if(this.rowHeader.definition.editor){
26634
+ console.warn("Using column editor with selectableRangeRows option may result in unpredictable behavior");
26635
+ }
26636
+ }
26637
+ }
26638
+ }
26639
+
26640
+ ///////////////////////////////////
26641
+ /////// Table Functions ///////
26642
+ ///////////////////////////////////
26643
+
26644
+ getRanges(){
26645
+ return this.ranges.map((range) => range.getComponent());
26646
+ }
26647
+
26648
+ getRangesData() {
26649
+ return this.ranges.map((range) => range.getData());
26650
+ }
26651
+
26652
+ addRangeFromComponent(start, end){
26653
+ start = start ? start._cell : null;
26654
+ end = end ? end._cell : null;
26655
+
26656
+ return this.addRange(start, end);
26657
+ }
26658
+
26659
+ ///////////////////////////////////
26660
+ /////// Component Functions ///////
26661
+ ///////////////////////////////////
26662
+
26663
+ cellGetRanges(cell){
26664
+ var ranges = [];
26665
+
26666
+ if (cell.column === this.rowHeader) {
26667
+ ranges = this.ranges.filter((range) => range.occupiesRow(cell.row));
26668
+ } else {
26669
+ ranges = this.ranges.filter((range) => range.occupies(cell));
26670
+ }
26671
+
26672
+ return ranges.map((range) => range.getComponent());
26673
+ }
26674
+
26675
+ rowGetRanges(row){
26676
+ var ranges = this.ranges.filter((range) => range.occupiesRow(row));
26677
+
26678
+ return ranges.map((range) => range.getComponent());
26679
+ }
26680
+
26681
+ colGetRanges(col){
26682
+ var ranges = this.ranges.filter((range) => range.occupiesColumn(col));
26683
+
26684
+ return ranges.map((range) => range.getComponent());
26685
+ }
26686
+
26687
+ ///////////////////////////////////
26688
+ ////////// Event Handlers /////////
26689
+ ///////////////////////////////////
26690
+
26691
+ _handleMouseUp(e){
26692
+ this.mousedown = false;
26693
+ document.removeEventListener("mouseup", this.mouseUpEvent);
26694
+ }
26695
+
26696
+ _handleKeyDown(e) {
26697
+ if (!this.blockKeydown && (!this.table.modules.edit || (this.table.modules.edit && !this.table.modules.edit.currentCell))) {
26698
+ if (e.key === "Enter") {
26699
+ // is editing a cell?
26700
+ if (this.table.modules.edit && this.table.modules.edit.currentCell) {
26701
+ return;
26702
+ }
26703
+
26704
+ this.table.modules.edit.editCell(this.getActiveCell());
26705
+
26706
+ e.preventDefault();
26707
+ }
26708
+
26709
+ if ((e.key === "Backspace" || e.key === "Delete") && this.options("selectableRangeClearCells")) {
26710
+ if(this.activeRange){
26711
+ this.activeRange.clearValues();
26712
+ }
26713
+ }
26714
+ }
26715
+ }
26716
+
26717
+ initializeFocus(cell){
26718
+ var range;
26719
+
26720
+ try{
26721
+ if (document.selection) { // IE
26722
+ range = document.body.createTextRange();
26723
+ range.moveToElementText(cell.getElement());
26724
+ range.select();
26725
+ } else if (window.getSelection) {
26726
+ range = document.createRange();
26727
+ range.selectNode(cell.getElement());
26728
+ window.getSelection().removeAllRanges();
26729
+ window.getSelection().addRange(range);
26730
+ }
26731
+ }catch(e){}
26732
+ }
26733
+
26734
+ restoreFocus(element){
26735
+ this.table.rowManager.element.focus();
26736
+
26737
+ return true;
26738
+ }
26739
+
26740
+ ///////////////////////////////////
26741
+ ////// Column Functionality ///////
26742
+ ///////////////////////////////////
26743
+
26744
+ handleColumnResized(column) {
26745
+ var selected;
26746
+
26747
+ if (this.selecting !== "column" && this.selecting !== "all") {
26748
+ return;
26749
+ }
26750
+
26751
+ selected = this.ranges.some((range) => range.occupiesColumn(column));
26752
+
26753
+ if (!selected) {
26754
+ return;
26755
+ }
26756
+
26757
+ this.ranges.forEach((range) => {
26758
+ var selectedColumns = range.getColumns(true);
26759
+
26760
+ selectedColumns.forEach((selectedColumn) => {
26761
+ if (selectedColumn !== column) {
26762
+ selectedColumn.setWidth(column.width);
26763
+ }
26764
+ });
26765
+ });
26766
+ }
26767
+
26768
+ handleColumnMouseDown(event, column) {
26769
+ if (event.button === 2 && (this.selecting === "column" || this.selecting === "all") && this.activeRange.occupiesColumn(column)) {
26770
+ return;
26771
+ }
26772
+
26773
+ this.mousedown = true;
26774
+
26775
+ document.addEventListener("mouseup", this.mouseUpEvent);
26776
+
26777
+ this.newSelection(event, column);
26778
+ }
26779
+
26780
+ handleColumnMouseMove(e, column) {
26781
+ if (column === this.rowHeader || !this.mousedown || this.selecting === 'all') {
26782
+ return;
26783
+ }
26784
+
26785
+ this.activeRange.setBounds(false, column, true);
26786
+ }
26787
+
26788
+ ///////////////////////////////////
26789
+ //////// Cell Functionality ///////
26790
+ ///////////////////////////////////
26791
+
26792
+ renderCell(cell) {
26793
+ var el = cell.getElement(),
26794
+ rangeIdx = this.ranges.findIndex((range) => range.occupies(cell));
26795
+
26796
+ el.classList.toggle("tabulator-range-selected", rangeIdx !== -1);
26797
+ el.classList.toggle("tabulator-range-only-cell-selected", this.ranges.length === 1 && this.ranges[0].atTopLeft(cell) && this.ranges[0].atBottomRight(cell));
26798
+
26799
+ el.dataset.range = rangeIdx;
26800
+ }
26801
+
26802
+ handleCellMouseDown(event, cell) {
26803
+ if (event.button === 2 && (this.activeRange.occupies(cell) || ((this.selecting === "row" || this.selecting === "all") && this.activeRange.occupiesRow(cell.row)))) {
26804
+ return;
26805
+ }
26806
+
26807
+ this.mousedown = true;
26808
+
26809
+ document.addEventListener("mouseup", this.mouseUpEvent);
26810
+
26811
+ this.newSelection(event, cell);
26812
+ }
26813
+
26814
+ handleCellMouseMove(e, cell) {
26815
+ if (!this.mousedown || this.selecting === "all") {
26816
+ return;
26817
+ }
26818
+
26819
+ this.activeRange.setBounds(false, cell, true);
26820
+ }
26821
+
26822
+ handleCellClick(e, cell){
26823
+ this.initializeFocus(cell);
26824
+ }
26825
+
26826
+ handleEditingCell(cell) {
26827
+ if(this.activeRange){
26828
+ this.activeRange.setBounds(cell);
26829
+ }
26830
+ }
26831
+
26832
+ finishEditingCell() {
26833
+ this.blockKeydown = true;
26834
+ this.table.rowManager.element.focus();
26835
+
26836
+ setTimeout(() => {
26837
+ this.blockKeydown = false;
26838
+ }, 10);
26839
+ }
26840
+
26841
+ ///////////////////////////////////
26842
+ /////// Navigation ///////
26843
+ ///////////////////////////////////
26844
+
26845
+ keyNavigate(dir, e){
26846
+ if(this.navigate(false, false, dir)){
26847
+ e.preventDefault();
26848
+ }
26849
+ }
26850
+
26851
+ keyNavigateRange(e, dir, jump, expand){
26852
+ if(this.navigate(jump, expand, dir)){
26853
+ e.preventDefault();
26854
+ }
26855
+ }
26856
+
26857
+ navigate(jump, expand, dir) {
26858
+ var moved = false,
26859
+ range, rangeEdge, nextRow, nextCol, row, column;
26860
+
26861
+ // Don't navigate while editing
26862
+ if (this.table.modules.edit && this.table.modules.edit.currentCell) {
26863
+ return false;
26864
+ }
26865
+
26866
+ // If there are more than 1 range, use the active range and destroy the others
26867
+ if (this.ranges.length > 1) {
26868
+ this.ranges = this.ranges.filter((range) => {
26869
+ if (range === this.activeRange) {
26870
+ range.setEnd(range.start.row, range.start.col);
26871
+ return true;
26872
+ }
26873
+ range.destroy();
26874
+ return false;
26875
+ });
26876
+ }
26877
+
26878
+ range = this.activeRange;
26879
+
26880
+ rangeEdge = expand ? range.end : range.start;
26881
+ nextRow = rangeEdge.row;
26882
+ nextCol = rangeEdge.col;
26883
+
26884
+ if(jump){
26885
+ switch(dir){
26886
+ case "left":
26887
+ nextCol = this.findJumpCellLeft(range.start.row, rangeEdge.col);
26888
+ break;
26889
+ case "right":
26890
+ nextCol = this.findJumpCellRight(range.start.row, rangeEdge.col);
26891
+ break;
26892
+ case "up":
26893
+ nextRow = this.findJumpCellUp(rangeEdge.row, range.start.col);
26894
+ break;
26895
+ case "down":
26896
+ nextRow = this.findJumpCellDown(rangeEdge.row, range.start.col);
26897
+ break;
26898
+ }
26899
+ }else {
26900
+ if(expand){
26901
+ if ((this.selecting === 'row' && (dir === 'left' || dir === 'right')) || (this.selecting === 'column' && (dir === 'up' || dir === 'down'))) {
26902
+ return;
26903
+ }
26904
+ }
26905
+
26906
+ switch(dir){
26907
+ case "left":
26908
+ nextCol = Math.max(nextCol - 1, 0);
26909
+ break;
26910
+ case "right":
26911
+ nextCol = Math.min(nextCol + 1, this.getTableColumns().length - 2);
26912
+ break;
26913
+ case "up":
26914
+ nextRow = Math.max(nextRow - 1, 0);
26915
+ break;
26916
+ case "down":
26917
+ nextRow = Math.min(nextRow + 1, this.getTableRows().length - 1);
26918
+ break;
26919
+ }
26920
+ }
26921
+
26922
+ moved = nextCol !== rangeEdge.col || nextRow !== rangeEdge.row;
26923
+
26924
+ if(!expand){
26925
+ range.setStart(nextRow, nextCol);
26926
+ }
26927
+
26928
+ range.setEnd(nextRow, nextCol);
26929
+
26930
+ if(!expand){
26931
+ this.selecting = "cell";
26932
+ }
26933
+
26934
+ if (moved) {
26935
+ row = this.getRowByRangePos(range.end.row);
26936
+ column = this.getColumnByRangePos(range.end.col);
26937
+
26938
+ if ((dir === 'left' || dir === 'right') && column.getElement().parentNode === null) {
26939
+ column.getComponent().scrollTo(undefined, false);
26940
+ } else if ((dir === 'up' || dir === 'down') && row.getElement().parentNode === null) {
26941
+ row.getComponent().scrollTo(undefined, false);
26942
+ } else {
26943
+ // Use faster autoScroll when the elements are on the DOM
26944
+ this.autoScroll(range, row.getElement(), column.getElement());
26945
+ }
26946
+
26947
+ this.layoutElement();
26948
+
26949
+ return true;
26950
+ }
26951
+ }
26952
+
26953
+ rangeRemoved(removed){
26954
+ this.ranges = this.ranges.filter((range) => range !== removed);
26955
+
26956
+ if(this.activeRange === removed){
26957
+ if(this.ranges.length){
26958
+ this.activeRange = this.ranges[this.ranges.length - 1];
26959
+ }else {
26960
+ this.addRange();
26961
+ }
26962
+ }
26963
+
26964
+ this.layoutElement();
26965
+ }
26966
+
26967
+ findJumpCell(cells, reverse, emptyStart, emptySide){
26968
+ var nextCell;
26969
+
26970
+ if(reverse){
26971
+ cells = cells.reverse();
26972
+ }
26973
+
26974
+ for(let currentCell of cells){
26975
+ let currentValue = currentCell.getValue();
26976
+
26977
+ if(emptyStart){
26978
+ nextCell = currentCell;
26979
+ if(currentValue){
26980
+ break;
26981
+ }
26982
+ }else {
26983
+ if(emptySide){
26984
+ nextCell = currentCell;
26985
+
26986
+ if(currentValue){
26987
+ break;
26988
+ }
26989
+ }else {
26990
+ if(currentValue){
26991
+ nextCell = currentCell;
26992
+ }else {
26993
+ break;
26994
+ }
26995
+ }
26996
+ }
26997
+ }
26998
+
26999
+ return nextCell;
27000
+ }
27001
+
27002
+ findJumpCellLeft(rowPos, colPos){
27003
+ var row = this.getRowByRangePos(rowPos),
27004
+ cells = row.cells.filter((cell) => cell.column.visible),
27005
+ isStartingCellEmpty = !cells[colPos + 1].getValue(),
27006
+ isLeftOfStartingCellEmpty = cells[colPos] ? !cells[colPos].getValue() : false,
27007
+ jumpCol = colPos,
27008
+ nextCell = this.findJumpCell(cells.slice(0, colPos), true, isStartingCellEmpty, isLeftOfStartingCellEmpty);
27009
+
27010
+ if(nextCell){
27011
+ jumpCol = nextCell.column.getPosition() - 2;
27012
+ }
27013
+
27014
+ return jumpCol;
27015
+ }
27016
+
27017
+ findJumpCellRight(rowPos, colPos){
27018
+ var row = this.getRowByRangePos(rowPos),
27019
+ cells = row.cells.filter((cell) => cell.column.visible),
27020
+ isStartingCellEmpty = !cells[colPos + 1].getValue(),
27021
+ isRightOfStartingCellEmpty = cells[colPos + 2] ? !cells[colPos + 2].getValue() : false,
27022
+ jumpCol = colPos,
27023
+ nextCell = this.findJumpCell(cells.slice(colPos + 2, cells.length), false, isStartingCellEmpty, isRightOfStartingCellEmpty);
27024
+
27025
+ if(nextCell){
27026
+ jumpCol = nextCell.column.getPosition() - 2;
27027
+ }
27028
+
27029
+ return jumpCol;
27030
+ }
27031
+
27032
+ findJumpCellUp(rowPos, colPos) {
27033
+ var column = this.getColumnByRangePos(colPos),
27034
+ cells = column.cells.filter((cell) => this.table.rowManager.activeRows.includes(cell.row)),
27035
+ isStartingCellEmpty = !cells[rowPos].getValue(),
27036
+ isTopOfStartingCellEmpty = cells[rowPos - 1] ? !cells[rowPos - 1].getValue() : false,
27037
+ jumpRow = rowPos,
27038
+ nextCell = this.findJumpCell(cells.slice(0, jumpRow), true, isStartingCellEmpty, isTopOfStartingCellEmpty);
27039
+
27040
+ if(nextCell){
27041
+ jumpRow = nextCell.row.position - 1;
27042
+ }
27043
+
27044
+ return jumpRow;
27045
+ }
27046
+
27047
+ findJumpCellDown(rowPos, colPos) {
27048
+ var column = this.getColumnByRangePos(colPos),
27049
+ cells = column.cells.filter((cell) => this.table.rowManager.activeRows.includes(cell.row)),
27050
+ isStartingCellEmpty = !cells[rowPos].getValue(),
27051
+ isBottomOfStartingCellEmpty = cells[rowPos + 1] ? !cells[rowPos + 1].getValue() : false,
27052
+ jumpRow = rowPos,
27053
+ nextCell = this.findJumpCell(cells.slice(jumpRow + 1, cells.length), false, isStartingCellEmpty, isBottomOfStartingCellEmpty);
27054
+
27055
+ if(nextCell){
27056
+ jumpRow = nextCell.row.position - 1;
27057
+ }
27058
+
27059
+ return jumpRow;
27060
+ }
27061
+
27062
+ ///////////////////////////////////
27063
+ /////// Selection ///////
27064
+ ///////////////////////////////////
27065
+ newSelection(event, element) {
27066
+ var range;
27067
+
27068
+ if (element.type === "column") {
27069
+ if(!this.columnSelection){
27070
+ return;
27071
+ }
27072
+
27073
+ if (element === this.rowHeader) {
27074
+ range = this.resetRanges();
27075
+ this.selecting = "all";
27076
+
27077
+ const topLeftCell = this.getCell(0, 0);
27078
+ const bottomRightCell = this.getCell(-1, -1);
27079
+
27080
+ range.setBounds(topLeftCell, bottomRightCell);
27081
+ return;
27082
+ } else {
27083
+ this.selecting = "column";
27084
+ }
27085
+ } else if (element.column === this.rowHeader) {
27086
+ this.selecting = "row";
27087
+ } else {
27088
+ this.selecting = "cell";
27089
+ }
27090
+
27091
+ if (event.shiftKey) {
27092
+ this.activeRange.setBounds(false, element);
27093
+ } else if (event.ctrlKey) {
27094
+ this.addRange().setBounds(element);
27095
+ } else {
27096
+ this.resetRanges().setBounds(element);
27097
+ }
27098
+ }
27099
+
27100
+ autoScroll(range, row, column) {
27101
+ var tableHolder = this.table.rowManager.element,
27102
+ rowHeader = this.rowHeader.getElement(),
27103
+ rect, view, withinHorizontalView, withinVerticalView;
27104
+
27105
+ if (typeof row === 'undefined') {
27106
+ row = this.getRowByRangePos(range.end.row).getElement();
27107
+ }
27108
+
27109
+ if (typeof column === 'undefined') {
27110
+ column = this.getColumnByRangePos(range.end.col).getElement();
27111
+ }
27112
+
27113
+ rect = {
27114
+ left: column.offsetLeft,
27115
+ right: column.offsetLeft + column.offsetWidth,
27116
+ top: row.offsetTop,
27117
+ bottom: row.offsetTop + row.offsetHeight,
27118
+ };
27119
+
27120
+ view = {
27121
+ left: tableHolder.scrollLeft + rowHeader.offsetWidth,
27122
+ right: Math.ceil(tableHolder.scrollLeft + tableHolder.clientWidth),
27123
+ top: tableHolder.scrollTop,
27124
+ bottom: tableHolder.scrollTop + tableHolder.offsetHeight - this.table.rowManager.scrollbarWidth,
27125
+ };
27126
+
27127
+ withinHorizontalView = view.left < rect.left && rect.left < view.right && view.left < rect.right && rect.right < view.right;
27128
+
27129
+ withinVerticalView = view.top < rect.top && rect.top < view.bottom && view.top < rect.bottom && rect.bottom < view.bottom;
27130
+
27131
+ if (!withinHorizontalView) {
27132
+ if (rect.left < view.left) {
27133
+ tableHolder.scrollLeft = rect.left - rowHeader.offsetWidth;
27134
+ } else if (rect.right > view.right) {
27135
+ tableHolder.scrollLeft = rect.right - tableHolder.clientWidth;
27136
+ }
27137
+ }
27138
+
27139
+ if (!withinVerticalView) {
27140
+ if (rect.top < view.top) {
27141
+ tableHolder.scrollTop = rect.top;
27142
+ } else if (rect.bottom > view.bottom) {
27143
+ tableHolder.scrollTop = rect.bottom - tableHolder.clientHeight;
27144
+ }
27145
+ }
27146
+ }
27147
+
27148
+
27149
+ ///////////////////////////////////
27150
+ /////// Layout ///////
27151
+ ///////////////////////////////////
27152
+
27153
+ layoutChange(){
27154
+ this.overlay.style.visibility = "hidden";
27155
+ clearTimeout(this.layoutChangeTimeout);
27156
+ this.layoutChangeTimeout = setTimeout(this.layoutRanges.bind(this), 200);
27157
+ }
27158
+
27159
+ redraw(force) {
27160
+ if (force) {
27161
+ this.selecting = 'cell';
27162
+ this.resetRanges();
27163
+ this.layoutElement();
27164
+ }
27165
+ }
27166
+
27167
+ layoutElement(visibleRows) {
27168
+ var rows;
27169
+
27170
+ if (visibleRows) {
27171
+ rows = this.table.rowManager.getVisibleRows(true);
27172
+ } else {
27173
+ rows = this.table.rowManager.getRows();
27174
+ }
27175
+
27176
+ rows.forEach((row) => {
27177
+ if (row.type === "row") {
27178
+ this.layoutRow(row);
27179
+ row.cells.forEach((cell) => this.renderCell(cell));
27180
+ }
27181
+ });
27182
+
27183
+ this.getTableColumns().forEach((column) => {
27184
+ this.layoutColumn(column);
27185
+ });
27186
+
27187
+ this.layoutRanges();
27188
+ }
27189
+
27190
+ layoutRow(row) {
27191
+ var el = row.getElement(),
27192
+ selected = false,
27193
+ occupied = this.ranges.some((range) => range.occupiesRow(row));
27194
+
27195
+ if (this.selecting === "row") {
27196
+ selected = occupied;
27197
+ } else if (this.selecting === "all") {
27198
+ selected = true;
27199
+ }
27200
+
27201
+ el.classList.toggle("tabulator-range-selected", selected);
27202
+ el.classList.toggle("tabulator-range-highlight", occupied);
27203
+ }
27204
+
27205
+ layoutColumn(column) {
27206
+ var el = column.getElement(),
27207
+ selected = false,
27208
+ occupied = this.ranges.some((range) => range.occupiesColumn(column));
27209
+
27210
+ if (this.selecting === "column") {
27211
+ selected = occupied;
27212
+ } else if (this.selecting === "all") {
27213
+ selected = true;
27214
+ }
27215
+
27216
+ el.classList.toggle("tabulator-range-selected", selected);
27217
+ el.classList.toggle("tabulator-range-highlight", occupied);
27218
+ }
27219
+
27220
+ layoutRanges() {
27221
+ var activeCell;
27222
+
27223
+ if (!this.table.initialized) {
27224
+ return;
27225
+ }
27226
+
27227
+ activeCell = this.getActiveCell();
27228
+
27229
+ if (!activeCell) {
27230
+ return;
27231
+ }
27232
+
27233
+ this.activeRangeCellElement.style.left = activeCell.row.getElement().offsetLeft + activeCell.getElement().offsetLeft + "px";
27234
+ this.activeRangeCellElement.style.top = activeCell.row.getElement().offsetTop + "px";
27235
+ this.activeRangeCellElement.style.width = activeCell.getElement().offsetLeft + activeCell.getElement().offsetWidth - activeCell.getElement().offsetLeft + "px";
27236
+ this.activeRangeCellElement.style.height = activeCell.row.getElement().offsetTop + activeCell.row.getElement().offsetHeight - activeCell.row.getElement().offsetTop + "px";
27237
+
27238
+ this.ranges.forEach((range) => range.layout());
27239
+
27240
+ this.overlay.style.visibility = "visible";
27241
+ }
27242
+
27243
+
27244
+ ///////////////////////////////////
27245
+ /////// Helper Functions ///////
27246
+ ///////////////////////////////////
27247
+
27248
+ getCell(rowIdx, colIdx) {
27249
+ var row;
27250
+
27251
+ if (colIdx < 0) {
27252
+ colIdx = this.getTableColumns().length + colIdx - 1;
27253
+
27254
+ if (colIdx < 0) {
27255
+ return null;
27256
+ }
27257
+ }
27258
+
27259
+ if (rowIdx < 0) {
27260
+ rowIdx = this.getTableRows().length + rowIdx;
27261
+ }
27262
+
27263
+ row = this.table.rowManager.getRowFromPosition(rowIdx + 1);
27264
+
27265
+ return row ? row.getCells(false, true).filter((cell) => cell.column.visible)[colIdx + 1] : null;
27266
+ }
27267
+
27268
+
27269
+ getActiveCell() {
27270
+ return this.getCell(this.activeRange.start.row, this.activeRange.start.col);
27271
+ }
27272
+
27273
+ getRowByRangePos(pos) {
27274
+ return this.getTableRows()[pos];
27275
+ }
27276
+
27277
+ getColumnByRangePos(pos) {
27278
+ return this.getTableColumns()[pos + 1];
27279
+ }
27280
+
27281
+ getTableRows() {
27282
+ return this.table.rowManager.getDisplayRows();
27283
+ }
27284
+
27285
+ getTableColumns() {
27286
+ return this.table.columnManager.getVisibleColumnsByIndex();
27287
+ }
27288
+
27289
+ addRange(start, end) {
27290
+ var range;
27291
+
27292
+ if(this.maxRanges !== true && this.ranges.length >= this.maxRanges){
27293
+ this.ranges.shift().destroy();
27294
+ }
27295
+
27296
+ range = new Range(this.table, this, start, end);
27297
+
27298
+ this.activeRange = range;
27299
+ this.ranges.push(range);
27300
+ this.rangeContainer.appendChild(range.element);
27301
+
27302
+ return range;
27303
+ }
27304
+
27305
+ resetRanges() {
27306
+ var range, cell;
27307
+
27308
+ this.ranges.forEach((range) => range.destroy());
27309
+ this.ranges = [];
27310
+
27311
+ range = this.addRange();
27312
+
27313
+ if(this.table.rowManager.activeRows.length){
27314
+ cell = this.table.rowManager.activeRows[0].cells[this.rowHeader ? 1 : 0];
27315
+
27316
+ if(cell){
27317
+ range.setBounds(cell);
27318
+ this.initializeFocus(cell);
27319
+ }
27320
+ }
27321
+
27322
+ return range;
27323
+ }
27324
+
27325
+ tableDestroyed(){
27326
+ document.removeEventListener("mouseup", this.mouseUpEvent);
27327
+ this.table.rowManager.element.removeEventListener("keydown", this.keyDownEvent);
27328
+ }
27329
+
27330
+ selectedRows(component) {
27331
+ return component ? this.activeRange.getRows().map((row) => row.getComponent()) : this.activeRange.getRows();
27332
+ }
27333
+
27334
+ selectedColumns(component) {
27335
+ return component ? this.activeRange.getColumns().map((col) => col.getComponent()) : this.activeRange.getColumns();
27336
+ }
27337
+ }
27338
+
27339
+ SelectRange.moduleName = "selectRange";
27340
+
27341
+ class Tooltip extends Module{
27342
+
27343
+ constructor(table){
27344
+ super(table);
27345
+
27346
+ this.tooltipSubscriber = null,
27347
+ this.headerSubscriber = null,
27348
+
27349
+ this.timeout = null;
27350
+ this.popupInstance = null;
27351
+
27352
+ this.registerTableOption("tooltipGenerationMode", undefined); //deprecated
27353
+ this.registerTableOption("tooltipDelay", 300);
27354
+
27355
+ this.registerColumnOption("tooltip");
27356
+ this.registerColumnOption("headerTooltip");
27357
+ }
27358
+
27359
+ initialize(){
27360
+ this.deprecatedOptionsCheck();
27361
+
27362
+ this.subscribe("column-init", this.initializeColumn.bind(this));
27363
+ }
27364
+
27365
+ deprecatedOptionsCheck(){
27366
+ this.deprecationCheckMsg("tooltipGenerationMode", "This option is no longer needed as tooltips are always generated on hover now");
27367
+ }
27368
+
27369
+ initializeColumn(column){
27370
+ if(column.definition.headerTooltip && !this.headerSubscriber){
27371
+ this.headerSubscriber = true;
27372
+
27373
+ this.subscribe("column-mousemove", this.mousemoveCheck.bind(this, "headerTooltip"));
27374
+ this.subscribe("column-mouseout", this.mouseoutCheck.bind(this, "headerTooltip"));
27375
+ }
27376
+
27377
+ if(column.definition.tooltip && !this.tooltipSubscriber){
27378
+ this.tooltipSubscriber = true;
25805
27379
 
25806
27380
  this.subscribe("cell-mousemove", this.mousemoveCheck.bind(this, "tooltip"));
25807
27381
  this.subscribe("cell-mouseout", this.mouseoutCheck.bind(this, "tooltip"));
@@ -25929,6 +27503,17 @@
25929
27503
  return isNaN(value);
25930
27504
  },
25931
27505
 
27506
+ //must be alphanumeric
27507
+ alphanumeric: function(cell, value, parameters){
27508
+ if(value === "" || value === null || typeof value === "undefined"){
27509
+ return true;
27510
+ }
27511
+
27512
+ var reg = new RegExp(/^[a-z0-9]+$/i);
27513
+
27514
+ return reg.test(value);
27515
+ },
27516
+
25932
27517
  //maximum value
25933
27518
  max: function(cell, value, parameters){
25934
27519
  if(value === "" || value === null || typeof value === "undefined"){
@@ -26365,6 +27950,7 @@
26365
27950
  ResponsiveLayoutModule: ResponsiveLayout,
26366
27951
  SelectRowModule: SelectRow,
26367
27952
  SortModule: Sort,
27953
+ SelectRangeModule: SelectRange,
26368
27954
  TooltipModule: Tooltip,
26369
27955
  ValidateModule: Validate
26370
27956
  });