tabulator-tables 5.4.4 → 5.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/bower.json +1 -1
  2. package/build/Bundler.js +7 -3
  3. package/dist/css/tabulator.css +85 -48
  4. package/dist/css/tabulator.css.map +1 -1
  5. package/dist/css/tabulator.min.css +1 -1
  6. package/dist/css/tabulator.min.css.map +1 -1
  7. package/dist/css/tabulator_bootstrap3.css +94 -53
  8. package/dist/css/tabulator_bootstrap3.css.map +1 -1
  9. package/dist/css/tabulator_bootstrap3.min.css +1 -1
  10. package/dist/css/tabulator_bootstrap3.min.css.map +1 -1
  11. package/dist/css/tabulator_bootstrap4.css +111 -68
  12. package/dist/css/tabulator_bootstrap4.css.map +1 -1
  13. package/dist/css/tabulator_bootstrap4.min.css +1 -1
  14. package/dist/css/tabulator_bootstrap4.min.css.map +1 -1
  15. package/dist/css/tabulator_bootstrap5.css +115 -70
  16. package/dist/css/tabulator_bootstrap5.css.map +1 -1
  17. package/dist/css/tabulator_bootstrap5.min.css +1 -1
  18. package/dist/css/tabulator_bootstrap5.min.css.map +1 -1
  19. package/dist/css/tabulator_bulma.css +100 -57
  20. package/dist/css/tabulator_bulma.css.map +1 -1
  21. package/dist/css/tabulator_bulma.min.css +1 -1
  22. package/dist/css/tabulator_bulma.min.css.map +1 -1
  23. package/dist/css/tabulator_materialize.css +109 -69
  24. package/dist/css/tabulator_materialize.css.map +1 -1
  25. package/dist/css/tabulator_materialize.min.css +1 -1
  26. package/dist/css/tabulator_materialize.min.css.map +1 -1
  27. package/dist/css/tabulator_midnight.css +95 -54
  28. package/dist/css/tabulator_midnight.css.map +1 -1
  29. package/dist/css/tabulator_midnight.min.css +1 -1
  30. package/dist/css/tabulator_midnight.min.css.map +1 -1
  31. package/dist/css/tabulator_modern.css +101 -57
  32. package/dist/css/tabulator_modern.css.map +1 -1
  33. package/dist/css/tabulator_modern.min.css +1 -1
  34. package/dist/css/tabulator_modern.min.css.map +1 -1
  35. package/dist/css/tabulator_semanticui.css +138 -77
  36. package/dist/css/tabulator_semanticui.css.map +1 -1
  37. package/dist/css/tabulator_semanticui.min.css +1 -1
  38. package/dist/css/tabulator_semanticui.min.css.map +1 -1
  39. package/dist/css/tabulator_simple.css +85 -48
  40. package/dist/css/tabulator_simple.css.map +1 -1
  41. package/dist/css/tabulator_simple.min.css +1 -1
  42. package/dist/css/tabulator_simple.min.css.map +1 -1
  43. package/dist/css/tabulator_site.css +93 -52
  44. package/dist/css/tabulator_site.css.map +1 -1
  45. package/dist/css/tabulator_site.min.css +1 -1
  46. package/dist/css/tabulator_site.min.css.map +1 -1
  47. package/dist/js/jquery_wrapper.js +10 -2
  48. package/dist/js/tabulator.js +507 -237
  49. package/dist/js/tabulator.js.map +1 -1
  50. package/dist/js/tabulator.min.js +2 -2
  51. package/dist/js/tabulator.min.js.map +1 -1
  52. package/dist/js/tabulator_esm.js +507 -237
  53. package/dist/js/tabulator_esm.js.map +1 -1
  54. package/dist/js/tabulator_esm.min.js +2 -2
  55. package/dist/js/tabulator_esm.min.js.map +1 -1
  56. package/package.json +3 -2
  57. package/src/js/builds/jquery_wrapper.js +10 -2
  58. package/src/js/core/ColumnManager.js +15 -0
  59. package/src/js/core/RowManager.js +59 -41
  60. package/src/js/core/cell/CellComponent.js +5 -3
  61. package/src/js/core/column/ColumnComponent.js +2 -2
  62. package/src/js/core/rendering/renderers/BasicHorizontal.js +12 -5
  63. package/src/js/core/rendering/renderers/BasicVertical.js +49 -28
  64. package/src/js/core/rendering/renderers/VirtualDomHorizontal.js +6 -1
  65. package/src/js/core/rendering/renderers/VirtualDomVertical.js +87 -30
  66. package/src/js/core/row/Row.js +9 -3
  67. package/src/js/core/row/RowComponent.js +2 -2
  68. package/src/js/core/tools/DataLoader.js +44 -36
  69. package/src/js/modules/ColumnCalcs/defaults/calculations.js +7 -0
  70. package/src/js/modules/DataTree/DataTree.js +5 -2
  71. package/src/js/modules/Download/defaults/downloaders/xlsx.js +5 -2
  72. package/src/js/modules/Edit/Edit.js +2 -3
  73. package/src/js/modules/Edit/List.js +14 -3
  74. package/src/js/modules/Edit/defaults/editors/date.js +1 -1
  75. package/src/js/modules/Edit/defaults/editors/datetime.js +1 -1
  76. package/src/js/modules/Edit/defaults/editors/input.js +1 -1
  77. package/src/js/modules/Edit/defaults/editors/number.js +1 -1
  78. package/src/js/modules/Edit/defaults/editors/range.js +1 -1
  79. package/src/js/modules/Edit/defaults/editors/textarea.js +1 -1
  80. package/src/js/modules/Edit/defaults/editors/tickCross.js +1 -1
  81. package/src/js/modules/Edit/defaults/editors/time.js +1 -1
  82. package/src/js/modules/Export/Export.js +3 -0
  83. package/src/js/modules/Filter/Filter.js +11 -0
  84. package/src/js/modules/Format/Format.js +3 -0
  85. package/src/js/modules/Format/defaults/formatters/money.js +9 -2
  86. package/src/js/modules/FrozenColumns/FrozenColumns.js +1 -1
  87. package/src/js/modules/GroupRows/Group.js +27 -10
  88. package/src/js/modules/GroupRows/GroupComponent.js +4 -0
  89. package/src/js/modules/History/defaults/redoers.js +4 -2
  90. package/src/js/modules/History/defaults/undoers.js +6 -2
  91. package/src/js/modules/Interaction/Interaction.js +12 -0
  92. package/src/js/modules/Persistence/Persistence.js +15 -1
  93. package/src/js/modules/ResponsiveLayout/ResponsiveLayout.js +3 -0
  94. package/src/js/modules/SelectRow/SelectRow.js +82 -54
  95. package/src/scss/tabulator.scss +87 -50
  96. package/src/scss/themes/bootstrap/tabulator_bootstrap3.scss +9 -5
  97. package/src/scss/themes/bootstrap/tabulator_bootstrap4.scss +27 -19
  98. package/src/scss/themes/bootstrap/tabulator_bootstrap5.scss +29 -19
  99. package/src/scss/themes/bulma/tabulator_bulma.scss +15 -9
  100. package/src/scss/themes/materialize/tabulator_materialize.scss +15 -11
  101. package/src/scss/themes/materialize/variables.scss +1 -1
  102. package/src/scss/themes/semanticui/tabulator_semanticui.scss +53 -28
  103. package/src/scss/themes/semanticui/variables_table.scss +1 -1
  104. package/src/scss/themes/tabulator_midnight.scss +10 -6
  105. package/src/scss/themes/tabulator_modern.scss +16 -8
  106. package/src/scss/themes/tabulator_site.scss +8 -4
@@ -1,4 +1,4 @@
1
- /* Tabulator v5.4.4 (c) Oliver Folkerd 2023 */
1
+ /* Tabulator v5.5.1 (c) Oliver Folkerd 2023 */
2
2
  class CoreFeature{
3
3
 
4
4
  constructor(table){
@@ -1505,10 +1505,12 @@ class CellComponent {
1505
1505
  return this._cell.row.getComponent();
1506
1506
  }
1507
1507
 
1508
- getData(){
1509
- return this._cell.row.getData();
1508
+ getData(transform){
1509
+ return this._cell.row.getData(transform);
1510
+ }
1511
+ getType(){
1512
+ return "cell";
1510
1513
  }
1511
-
1512
1514
  getField(){
1513
1515
  return this._cell.column.getField();
1514
1516
  }
@@ -1938,8 +1940,8 @@ class ColumnComponent {
1938
1940
  return this._column;
1939
1941
  }
1940
1942
 
1941
- scrollTo(){
1942
- return this._column.table.columnManager.scrollToColumn(this._column);
1943
+ scrollTo(position, ifVisible){
1944
+ return this._column.table.columnManager.scrollToColumn(this._column, position, ifVisible);
1943
1945
  }
1944
1946
 
1945
1947
  getTable(){
@@ -3008,8 +3010,8 @@ class RowComponent {
3008
3010
  return this._row.delete();
3009
3011
  }
3010
3012
 
3011
- scrollTo(){
3012
- return this._row.table.rowManager.scrollToRow(this._row);
3013
+ scrollTo(position, ifVisible){
3014
+ return this._row.table.rowManager.scrollToRow(this._row, position, ifVisible);
3013
3015
  }
3014
3016
 
3015
3017
  move(to, after){
@@ -3110,7 +3112,7 @@ class Row extends CoreFeature{
3110
3112
  }
3111
3113
 
3112
3114
  //functions to setup on first render
3113
- initialize(force){
3115
+ initialize(force, inFragment){
3114
3116
  this.create();
3115
3117
 
3116
3118
  if(!this.initialized || force){
@@ -3125,7 +3127,7 @@ class Row extends CoreFeature{
3125
3127
 
3126
3128
  this.initialized = true;
3127
3129
 
3128
- this.table.columnManager.renderer.renderRowCells(this);
3130
+ this.table.columnManager.renderer.renderRowCells(this, inFragment);
3129
3131
 
3130
3132
  if(force){
3131
3133
  this.normalizeHeight();
@@ -3139,9 +3141,15 @@ class Row extends CoreFeature{
3139
3141
 
3140
3142
  this.dispatch("row-layout-after", this);
3141
3143
  }else {
3142
- this.table.columnManager.renderer.rerenderRowCells(this);
3144
+ this.table.columnManager.renderer.rerenderRowCells(this, inFragment);
3143
3145
  }
3144
3146
  }
3147
+
3148
+ rendered(){
3149
+ this.cells.forEach((cell) => {
3150
+ cell.cellRendered();
3151
+ });
3152
+ }
3145
3153
 
3146
3154
  reinitializeHeight(){
3147
3155
  this.heightInitialized = false;
@@ -3586,6 +3594,13 @@ var defaultCalculations = {
3586
3594
 
3587
3595
  return output;
3588
3596
  },
3597
+ "unique":function(values, data, calcParams){
3598
+ var unique = values.filter((value, index) => {
3599
+ return (values || value === 0) && values.indexOf(value) === index;
3600
+ });
3601
+
3602
+ return unique.length;
3603
+ },
3589
3604
  };
3590
3605
 
3591
3606
  class ColumnCalcs extends Module{
@@ -4222,6 +4237,9 @@ class DataTree extends Module{
4222
4237
  this.branchEl = options.dataTreeBranchElement;
4223
4238
  }
4224
4239
  }
4240
+ }else {
4241
+ this.branchEl = document.createElement("div");
4242
+ this.branchEl.classList.add("tabulator-data-tree-branch-empty");
4225
4243
  }
4226
4244
 
4227
4245
  if(options.dataTreeCollapseElement){
@@ -4460,7 +4478,7 @@ class DataTree extends Module{
4460
4478
 
4461
4479
  row.create();
4462
4480
 
4463
- config = row.modules.dataTree.children;
4481
+ config = row.modules.dataTree;
4464
4482
 
4465
4483
  if(!config.index && config.children !== false){
4466
4484
  children = this.getChildren(row);
@@ -4725,7 +4743,7 @@ class DataTree extends Module{
4725
4743
  var config = row.modules.dataTree,
4726
4744
  output = [];
4727
4745
 
4728
- if(config.children){
4746
+ if(config && config.children){
4729
4747
 
4730
4748
  if(!Array.isArray(config.children)){
4731
4749
  config.children = this.generateChildren(row);
@@ -4971,8 +4989,11 @@ function xlsx(list, options, setFileContents){
4971
4989
  workbook = XLSX.utils.book_new(),
4972
4990
  tableFeatures = new CoreFeature(this),
4973
4991
  compression = 'compress' in options ? options.compress : true,
4992
+ writeOptions = options.writeOptions || {bookType:'xlsx', bookSST:true, compression},
4974
4993
  output;
4975
4994
 
4995
+ writeOptions.type = 'binary';
4996
+
4976
4997
  workbook.SheetNames = [];
4977
4998
  workbook.Sheets = {};
4978
4999
 
@@ -5058,7 +5079,7 @@ function xlsx(list, options, setFileContents){
5058
5079
  return buf;
5059
5080
  }
5060
5081
 
5061
- output = XLSX.write(workbook, {bookType:'xlsx', bookSST:true, type: 'binary', compression });
5082
+ output = XLSX.write(workbook, writeOptions);
5062
5083
 
5063
5084
  setFileContents(s2ab(output), "application/octet-stream");
5064
5085
  }
@@ -5356,7 +5377,7 @@ function input(cell, onRendered, success, cancel, editorParams){
5356
5377
  input.value = typeof cellValue !== "undefined" ? cellValue : "";
5357
5378
 
5358
5379
  onRendered(function(){
5359
- if(cell._getSelf){
5380
+ if(cell.getType() === "cell"){
5360
5381
  input.focus({preventScroll: true});
5361
5382
  input.style.height = "100%";
5362
5383
 
@@ -5437,7 +5458,7 @@ function textarea(cell, onRendered, success, cancel, editorParams){
5437
5458
  input.value = value;
5438
5459
 
5439
5460
  onRendered(function(){
5440
- if(cell._getSelf){
5461
+ if(cell.getType() === "cell"){
5441
5462
  input.focus({preventScroll: true});
5442
5463
  input.style.height = "100%";
5443
5464
 
@@ -5571,7 +5592,7 @@ function number(cell, onRendered, success, cancel, editorParams){
5571
5592
  };
5572
5593
 
5573
5594
  onRendered(function () {
5574
- if(cell._getSelf){
5595
+ if(cell.getType() === "cell"){
5575
5596
  //submit new value on blur
5576
5597
  input.removeEventListener("blur", blurFunc);
5577
5598
 
@@ -5675,7 +5696,7 @@ function range(cell, onRendered, success, cancel, editorParams){
5675
5696
  input.value = cellValue;
5676
5697
 
5677
5698
  onRendered(function () {
5678
- if(cell._getSelf){
5699
+ if(cell.getType() === "cell"){
5679
5700
  input.focus({preventScroll: true});
5680
5701
  input.style.height = "100%";
5681
5702
  }
@@ -5780,7 +5801,7 @@ function date(cell, onRendered, success, cancel, editorParams){
5780
5801
  input.value = cellValue;
5781
5802
 
5782
5803
  onRendered(function(){
5783
- if(cell._getSelf){
5804
+ if(cell.getType() === "cell"){
5784
5805
  input.focus({preventScroll: true});
5785
5806
  input.style.height = "100%";
5786
5807
 
@@ -5907,7 +5928,7 @@ function time(cell, onRendered, success, cancel, editorParams){
5907
5928
  input.value = cellValue;
5908
5929
 
5909
5930
  onRendered(function(){
5910
- if(cell._getSelf){
5931
+ if(cell.getType() == "cell"){
5911
5932
  input.focus({preventScroll: true});
5912
5933
  input.style.height = "100%";
5913
5934
 
@@ -6033,7 +6054,7 @@ function datetime(cell, onRendered, success, cancel, editorParams){
6033
6054
  input.value = cellValue;
6034
6055
 
6035
6056
  onRendered(function(){
6036
- if(cell._getSelf){
6057
+ if(cell.getType() === "cell"){
6037
6058
  input.focus({preventScroll: true});
6038
6059
  input.style.height = "100%";
6039
6060
 
@@ -6128,7 +6149,7 @@ class Edit{
6128
6149
 
6129
6150
  this.initialValues = null;
6130
6151
 
6131
- this.isFilter = !cell._getSelf;
6152
+ this.isFilter = cell.getType() === "header";
6132
6153
 
6133
6154
  this.filterTimeout = null;
6134
6155
  this.filtered = false;
@@ -6194,7 +6215,7 @@ class Edit{
6194
6215
  function clickStop(e){
6195
6216
  e.stopPropagation();
6196
6217
  }
6197
-
6218
+
6198
6219
  if(!this.isFilter){
6199
6220
  this.input.style.height = "100%";
6200
6221
  this.input.focus({preventScroll: true});
@@ -6418,6 +6439,7 @@ class Edit{
6418
6439
  break;
6419
6440
 
6420
6441
  case 9: //tab
6442
+ this._keyTab(e);
6421
6443
  break;
6422
6444
 
6423
6445
  default:
@@ -6464,6 +6486,16 @@ class Edit{
6464
6486
  //////// Keyboard Navigation /////////
6465
6487
  //////////////////////////////////////
6466
6488
 
6489
+ _keyTab(e){
6490
+ if(this.params.autocomplete && this.lastAction === "typing"){
6491
+ this._resolveValue(true);
6492
+ }else {
6493
+ if(this.focusedItem){
6494
+ this._chooseItem(this.focusedItem, true);
6495
+ }
6496
+ }
6497
+ }
6498
+
6467
6499
  _keyUp(e){
6468
6500
  var index = this.displayItems.indexOf(this.focusedItem);
6469
6501
 
@@ -7101,7 +7133,7 @@ class Edit{
7101
7133
 
7102
7134
  _resolveValue(blur){
7103
7135
  var output, initialValue;
7104
-
7136
+
7105
7137
  if(this.popup){
7106
7138
  this.popup.hide(true);
7107
7139
  }
@@ -7481,7 +7513,7 @@ function tickCross(cell, onRendered, success, cancel, editorParams){
7481
7513
 
7482
7514
  if(this.table.browser != "firefox" && this.table.browser != "safari"){ //prevent blur issue on mac firefox
7483
7515
  onRendered(function(){
7484
- if(cell._getSelf){
7516
+ if(cell.getType() === "cell"){
7485
7517
  input.focus({preventScroll: true});
7486
7518
  }
7487
7519
  });
@@ -8070,8 +8102,8 @@ class Edit$1 extends Module{
8070
8102
  cellEl = cell.getElement();
8071
8103
 
8072
8104
  if(this.table.modExists("frozenColumns")){
8073
- leftEdge += parseInt(this.table.modules.frozenColumns.leftMargin);
8074
- rightEdge -= parseInt(this.table.modules.frozenColumns.rightMargin);
8105
+ leftEdge += parseInt(this.table.modules.frozenColumns.leftMargin || 0);
8106
+ rightEdge -= parseInt(this.table.modules.frozenColumns.rightMargin || 0);
8075
8107
  }
8076
8108
 
8077
8109
  if(this.table.options.renderHorizontal === "virtual"){
@@ -8080,7 +8112,6 @@ class Edit$1 extends Module{
8080
8112
  }
8081
8113
 
8082
8114
  if(cellEl.offsetLeft < leftEdge){
8083
-
8084
8115
  this.table.rowManager.element.scrollLeft -= (leftEdge - cellEl.offsetLeft);
8085
8116
  }else {
8086
8117
  if(cellEl.offsetLeft + cellEl.offsetWidth > rightEdge){
@@ -8788,6 +8819,9 @@ class Export extends Module{
8788
8819
  getElement:function(){
8789
8820
  return cellEl;
8790
8821
  },
8822
+ getType:function(){
8823
+ return "cell";
8824
+ },
8791
8825
  getColumn:function(){
8792
8826
  return column.getComponent();
8793
8827
  },
@@ -9048,6 +9082,7 @@ class Filter extends Module{
9048
9082
  this.registerTableOption("initialFilter", false); //initial filtering criteria
9049
9083
  this.registerTableOption("initialHeaderFilter", false); //initial header filtering criteria
9050
9084
  this.registerTableOption("headerFilterLiveFilterDelay", 300); //delay before updating column after user types in header filter
9085
+ this.registerTableOption("placeholderHeaderFilter", false); //placeholder when header filter is empty
9051
9086
 
9052
9087
  this.registerColumnOption("headerFilter");
9053
9088
  this.registerColumnOption("headerFilterPlaceholder");
@@ -9083,6 +9118,7 @@ class Filter extends Module{
9083
9118
  this.subscribe("column-width-fit-before", this.hideHeaderFilterElements.bind(this));
9084
9119
  this.subscribe("column-width-fit-after", this.showHeaderFilterElements.bind(this));
9085
9120
  this.subscribe("table-built", this.tableBuilt.bind(this));
9121
+ this.subscribe("placeholder", this.generatePlaceholder.bind(this));
9086
9122
 
9087
9123
  if(this.table.options.filterMode === "remote"){
9088
9124
  this.subscribe("data-params", this.remoteFilterParams.bind(this));
@@ -9118,6 +9154,12 @@ class Filter extends Module{
9118
9154
  return params;
9119
9155
  }
9120
9156
 
9157
+ generatePlaceholder(text){
9158
+ if(this.table.options.placeholderHeaderFilter && Object.keys(this.headerFilters).length){
9159
+ return this.table.options.placeholderHeaderFilter;
9160
+ }
9161
+ }
9162
+
9121
9163
  ///////////////////////////////////
9122
9164
  ///////// Table Functions /////////
9123
9165
  ///////////////////////////////////
@@ -9401,6 +9443,9 @@ class Filter extends Module{
9401
9443
  getTable:() => {
9402
9444
  return this.table;
9403
9445
  },
9446
+ getType:() => {
9447
+ return "header";
9448
+ },
9404
9449
  getRow:function(){
9405
9450
  return {
9406
9451
  normalizeHeight:function(){
@@ -9932,7 +9977,7 @@ function textarea$1(cell, formatterParams, onRendered){
9932
9977
  function money(cell, formatterParams, onRendered){
9933
9978
  var floatVal = parseFloat(cell.getValue()),
9934
9979
  sign = "",
9935
- number, integer, decimal, rgx;
9980
+ number, integer, decimal, rgx, value;
9936
9981
 
9937
9982
  var decimalSym = formatterParams.decimal || ".";
9938
9983
  var thousandSym = formatterParams.thousand || ",";
@@ -9964,7 +10009,14 @@ function money(cell, formatterParams, onRendered){
9964
10009
  }
9965
10010
  }
9966
10011
 
9967
- return after ? sign + integer + decimal + symbol : sign + symbol + integer + decimal;
10012
+ value = integer + decimal;
10013
+
10014
+ if(sign === true){
10015
+ value = "(" + value + ")";
10016
+ return after ? value + symbol : symbol + value;
10017
+ }else {
10018
+ return after ? sign + value + symbol : sign + symbol + value;
10019
+ }
9968
10020
  }
9969
10021
 
9970
10022
  function link(cell, formatterParams, onRendered){
@@ -10670,6 +10722,9 @@ class Format extends Module{
10670
10722
  getElement:function(){
10671
10723
  return el;
10672
10724
  },
10725
+ getType:function(){
10726
+ return "header";
10727
+ },
10673
10728
  getColumn:function(){
10674
10729
  return column.getComponent();
10675
10730
  },
@@ -11041,7 +11096,7 @@ class FrozenColumns extends Module{
11041
11096
  layoutElement(element, column){
11042
11097
  var position;
11043
11098
 
11044
- if(column.modules.frozen){
11099
+ if(column.modules.frozen && element){
11045
11100
  element.style.position = "sticky";
11046
11101
 
11047
11102
  if(this.table.rtl){
@@ -11305,6 +11360,10 @@ class GroupComponent {
11305
11360
  this._group.toggleVisibility();
11306
11361
  }
11307
11362
 
11363
+ scrollTo(position, ifVisible){
11364
+ return this._group.groupManager.table.rowManager.scrollToRow(this._group, position, ifVisible);
11365
+ }
11366
+
11308
11367
  _getSelf(){
11309
11368
  return this._group;
11310
11369
  }
@@ -11384,7 +11443,7 @@ class Group{
11384
11443
  this.arrowElement = document.createElement("div");
11385
11444
  this.arrowElement.classList.add("tabulator-group-toggle");
11386
11445
  this.arrowElement.appendChild(arrow);
11387
-
11446
+
11388
11447
  //setup movable rows
11389
11448
  if(this.groupManager.table.options.movableRows !== false && this.groupManager.table.modExists("moveRow")){
11390
11449
  this.groupManager.table.modules.moveRow.initializeGroupHeader(this);
@@ -11407,9 +11466,15 @@ class Group{
11407
11466
  toggleElement = this.groupManager.table.options.groupToggleElement == "arrow" ? this.arrowElement : this.element;
11408
11467
 
11409
11468
  toggleElement.addEventListener("click", (e) => {
11410
- e.stopPropagation();
11411
- e.stopImmediatePropagation();
11412
- this.toggleVisibility();
11469
+ if(this.groupManager.table.options.groupToggleElement === "arrow"){
11470
+ e.stopPropagation();
11471
+ e.stopImmediatePropagation();
11472
+ }
11473
+
11474
+ //allow click event to propagate before toggling visibility
11475
+ setTimeout(() => {
11476
+ this.toggleVisibility();
11477
+ });
11413
11478
  });
11414
11479
  }
11415
11480
  }
@@ -11530,7 +11595,7 @@ class Group{
11530
11595
  if(el.parentNode){
11531
11596
  el.parentNode.removeChild(el);
11532
11597
  }
11533
-
11598
+
11534
11599
  if(!this.groupManager.blockRedraw){
11535
11600
  this.generateGroupHeaderContents();
11536
11601
 
@@ -11655,6 +11720,7 @@ class Group{
11655
11720
  }
11656
11721
  return count;
11657
11722
  }
11723
+
11658
11724
 
11659
11725
  toggleVisibility(){
11660
11726
  if(this.visible){
@@ -11779,12 +11845,18 @@ class Group{
11779
11845
  return output;
11780
11846
  }
11781
11847
 
11782
- getRows(component){
11848
+ getRows(component, includeChildren){
11783
11849
  var output = [];
11784
11850
 
11785
- this.rows.forEach(function(row){
11786
- output.push(component ? row.getComponent() : row);
11787
- });
11851
+ if(includeChildren && this.groupList.length){
11852
+ this.groupList.forEach((group) => {
11853
+ output = output.concat(group.getRows(component, includeChildren));
11854
+ });
11855
+ }else {
11856
+ this.rows.forEach(function(row){
11857
+ output.push(component ? row.getComponent() : row);
11858
+ });
11859
+ }
11788
11860
 
11789
11861
  return output;
11790
11862
  }
@@ -11792,7 +11864,9 @@ class Group{
11792
11864
  generateGroupHeaderContents(){
11793
11865
  var data = [];
11794
11866
 
11795
- this.rows.forEach(function(row){
11867
+ var rows = this.getRows(false, true);
11868
+
11869
+ rows.forEach(function(row){
11796
11870
  data.push(row.getData());
11797
11871
  });
11798
11872
 
@@ -11897,6 +11971,8 @@ class Group{
11897
11971
  clearCellHeight(){}
11898
11972
 
11899
11973
  deinitializeHeight(){}
11974
+
11975
+ rendered(){}
11900
11976
 
11901
11977
  //////////////// Object Generation /////////////////
11902
11978
  getComponent(){
@@ -12563,8 +12639,12 @@ var defaultUndoers = {
12563
12639
  },
12564
12640
 
12565
12641
  rowMove: function(action){
12566
- this.table.rowManager.moveRowActual(action.component, this.table.rowManager.rows[action.data.posFrom], !action.data.after);
12567
- this.table.rowManager.redraw();
12642
+ var after = (action.data.posFrom - action.data.posTo) > 0;
12643
+
12644
+ this.table.rowManager.moveRowActual(action.component, this.table.rowManager.getRowFromPosition(action.data.posFrom), after);
12645
+
12646
+ this.table.rowManager.regenerateRowPositions();
12647
+ this.table.rowManager.reRenderInPosition();
12568
12648
  },
12569
12649
  };
12570
12650
 
@@ -12589,8 +12669,10 @@ var defaultRedoers = {
12589
12669
  },
12590
12670
 
12591
12671
  rowMove: function(action){
12592
- this.table.rowManager.moveRowActual(action.component, this.table.rowManager.rows[action.data.posTo], action.data.after);
12593
- this.table.rowManager.redraw();
12672
+ this.table.rowManager.moveRowActual(action.component, this.table.rowManager.getRowFromPosition(action.data.posTo), action.data.after);
12673
+
12674
+ this.table.rowManager.regenerateRowPositions();
12675
+ this.table.rowManager.reRenderInPosition();
12594
12676
  },
12595
12677
  };
12596
12678
 
@@ -13338,8 +13420,20 @@ class Interaction extends Module{
13338
13420
 
13339
13421
  this.subscribe("column-init", this.initializeColumn.bind(this));
13340
13422
  this.subscribe("cell-dblclick", this.cellContentsSelectionFixer.bind(this));
13423
+ this.subscribe("scroll-horizontal", this.clearTouchWatchers.bind(this));
13424
+ this.subscribe("scroll-vertical", this.clearTouchWatchers.bind(this));
13341
13425
  }
13342
13426
 
13427
+ clearTouchWatchers(){
13428
+ var types = Object.values(this.touchWatchers);
13429
+
13430
+ types.forEach((type) => {
13431
+ for(let key in type){
13432
+ type[key] = null;
13433
+ }
13434
+ });
13435
+ }
13436
+
13343
13437
  cellContentsSelectionFixer(e, cell){
13344
13438
  var range;
13345
13439
 
@@ -16295,6 +16389,7 @@ class Persistence extends Module{
16295
16389
  this.config = {
16296
16390
  sort:this.table.options.persistence === true || this.table.options.persistence.sort,
16297
16391
  filter:this.table.options.persistence === true || this.table.options.persistence.filter,
16392
+ headerFilter:this.table.options.persistence === true || this.table.options.persistence.headerFilter,
16298
16393
  group:this.table.options.persistence === true || this.table.options.persistence.group,
16299
16394
  page:this.table.options.persistence === true || this.table.options.persistence.page,
16300
16395
  columns:this.table.options.persistence === true ? ["title", "width", "visible"] : this.table.options.persistence.columns,
@@ -16345,6 +16440,7 @@ class Persistence extends Module{
16345
16440
  this.subscribe("table-redraw", this.tableRedraw.bind(this));
16346
16441
 
16347
16442
  this.subscribe("filter-changed", this.eventSave.bind(this, "filter"));
16443
+ this.subscribe("filter-changed", this.eventSave.bind(this, "headerFilter"));
16348
16444
  this.subscribe("sort-changed", this.eventSave.bind(this, "sort"));
16349
16445
  this.subscribe("group-changed", this.eventSave.bind(this, "group"));
16350
16446
  this.subscribe("page-changed", this.eventSave.bind(this, "page"));
@@ -16364,7 +16460,7 @@ class Persistence extends Module{
16364
16460
  }
16365
16461
 
16366
16462
  tableBuilt(){
16367
- var sorters, filters;
16463
+ var sorters, filters, headerFilters;
16368
16464
 
16369
16465
  if(this.config.sort){
16370
16466
  sorters = this.load("sort");
@@ -16381,6 +16477,14 @@ class Persistence extends Module{
16381
16477
  this.table.options.initialFilter = filters;
16382
16478
  }
16383
16479
  }
16480
+ if(this.config.headerFilter){
16481
+ headerFilters = this.load("headerFilter");
16482
+
16483
+ if(!headerFilters === false){
16484
+ this.table.options.initialHeaderFilter = headerFilters;
16485
+ }
16486
+ }
16487
+
16384
16488
  }
16385
16489
 
16386
16490
  tableRedraw(force){
@@ -16541,6 +16645,10 @@ class Persistence extends Module{
16541
16645
  data = this.table.modules.filter.getFilters();
16542
16646
  break;
16543
16647
 
16648
+ case "headerFilter":
16649
+ data = this.table.modules.filter.getHeaderFilters();
16650
+ break;
16651
+
16544
16652
  case "sort":
16545
16653
  data = this.validateSorters(this.table.modules.sort.getSort());
16546
16654
  break;
@@ -18273,6 +18381,9 @@ class ResponsiveLayout extends Module{
18273
18381
  getData:function(){
18274
18382
  return data;
18275
18383
  },
18384
+ getType:function(){
18385
+ return "cell";
18386
+ },
18276
18387
  getElement:function(){
18277
18388
  return document.createElement("div");
18278
18389
  },
@@ -18537,7 +18648,7 @@ class SelectRow extends Module{
18537
18648
  }
18538
18649
 
18539
18650
  checkRowSelectability(row){
18540
- if(row.type === "row"){
18651
+ if(row && row.type === "row"){
18541
18652
  return this.table.options.selectableCheck.call(this.table, row.getComponent());
18542
18653
  }
18543
18654
 
@@ -18557,48 +18668,44 @@ class SelectRow extends Module{
18557
18668
 
18558
18669
  //select a number of rows
18559
18670
  selectRows(rows){
18560
- var rowMatch;
18671
+ var changes = [],
18672
+ rowMatch, change;
18561
18673
 
18562
18674
  switch(typeof rows){
18563
18675
  case "undefined":
18564
- this.table.rowManager.rows.forEach((row) => {
18565
- this._selectRow(row, true, true);
18566
- });
18567
-
18568
- this._rowSelectionChanged();
18676
+ rowMatch = this.table.rowManager.rows;
18569
18677
  break;
18570
18678
 
18571
18679
  case "string":
18572
18680
  rowMatch = this.table.rowManager.findRow(rows);
18573
18681
 
18574
- if(rowMatch){
18575
- this._selectRow(rowMatch, true, true);
18576
- this._rowSelectionChanged();
18577
- }else {
18682
+ if(!rowMatch){
18578
18683
  rowMatch = this.table.rowManager.getRows(rows);
18579
-
18580
- rowMatch.forEach((row) => {
18581
- this._selectRow(row, true, true);
18582
- });
18583
-
18584
- if(rowMatch.length){
18585
- this._rowSelectionChanged();
18586
- }
18587
18684
  }
18588
18685
  break;
18589
18686
 
18590
18687
  default:
18591
- if(Array.isArray(rows)){
18592
- rows.forEach((row) => {
18593
- this._selectRow(row, true, true);
18594
- });
18595
-
18596
- this._rowSelectionChanged();
18597
- }else {
18598
- this._selectRow(rows, false, true);
18599
- }
18688
+ rowMatch = rows;
18600
18689
  break;
18601
18690
  }
18691
+
18692
+ if(Array.isArray(rowMatch)){
18693
+ if(rowMatch.length){
18694
+ rowMatch.forEach((row) => {
18695
+ change = this._selectRow(row, true, true);
18696
+
18697
+ if(change){
18698
+ changes.push(change);
18699
+ }
18700
+ });
18701
+
18702
+ this._rowSelectionChanged(false, changes);
18703
+ }
18704
+ }else {
18705
+ if(rowMatch){
18706
+ this._selectRow(rowMatch, false, true);
18707
+ }
18708
+ }
18602
18709
  }
18603
18710
 
18604
18711
  //select an individual row
@@ -18636,7 +18743,9 @@ class SelectRow extends Module{
18636
18743
 
18637
18744
  this.dispatchExternal("rowSelected", row.getComponent());
18638
18745
 
18639
- this._rowSelectionChanged(silent);
18746
+ this._rowSelectionChanged(silent, row);
18747
+
18748
+ return row;
18640
18749
  }
18641
18750
  }else {
18642
18751
  if(!silent){
@@ -18651,39 +18760,51 @@ class SelectRow extends Module{
18651
18760
 
18652
18761
  //deselect a number of rows
18653
18762
  deselectRows(rows, silent){
18654
- var self = this,
18655
- rowCount;
18763
+ var changes = [],
18764
+ rowMatch, change;
18656
18765
 
18657
- if(typeof rows == "undefined"){
18766
+ switch(typeof rows){
18767
+ case "undefined":
18768
+ rowMatch = Object.assign([], this.selectedRows);
18769
+ break;
18658
18770
 
18659
- rowCount = self.selectedRows.length;
18771
+ case "string":
18772
+ rowMatch = this.table.rowManager.findRow(rows);
18660
18773
 
18661
- for(let i = 0; i < rowCount; i++){
18662
- self._deselectRow(self.selectedRows[0], true);
18663
- }
18774
+ if(!rowMatch){
18775
+ rowMatch = this.table.rowManager.getRows(rows);
18776
+ }
18777
+ break;
18664
18778
 
18665
- if(rowCount){
18666
- self._rowSelectionChanged(silent);
18779
+ default:
18780
+ rowMatch = rows;
18781
+ break;
18782
+ }
18783
+
18784
+ if(Array.isArray(rowMatch)){
18785
+ if(rowMatch.length){
18786
+ rowMatch.forEach((row) => {
18787
+ change = this._deselectRow(row, true, true);
18788
+
18789
+ if(change){
18790
+ changes.push(change);
18791
+ }
18792
+ });
18793
+
18794
+ this._rowSelectionChanged(silent, [], changes);
18667
18795
  }
18668
-
18669
18796
  }else {
18670
- if(Array.isArray(rows)){
18671
- rows.forEach(function(row){
18672
- self._deselectRow(row, true);
18673
- });
18674
-
18675
- self._rowSelectionChanged(silent);
18676
- }else {
18677
- self._deselectRow(rows, silent);
18797
+ if(rowMatch){
18798
+ this._deselectRow(rowMatch, silent, true);
18678
18799
  }
18679
- }
18800
+ }
18680
18801
  }
18681
18802
 
18682
18803
  //deselect an individual row
18683
18804
  _deselectRow(rowInfo, silent){
18684
18805
  var self = this,
18685
18806
  row = self.table.rowManager.findRow(rowInfo),
18686
- index;
18807
+ index, element;
18687
18808
 
18688
18809
  if(row){
18689
18810
  index = self.selectedRows.findIndex(function(selectedRow){
@@ -18691,8 +18812,13 @@ class SelectRow extends Module{
18691
18812
  });
18692
18813
 
18693
18814
  if(index > -1){
18815
+
18816
+ element = row.getElement();
18817
+
18818
+ if(element){
18819
+ element.classList.remove("tabulator-selected");
18820
+ }
18694
18821
 
18695
- row.getElement().classList.remove("tabulator-selected");
18696
18822
  if(!row.modules.select){
18697
18823
  row.modules.select = {};
18698
18824
  }
@@ -18709,7 +18835,9 @@ class SelectRow extends Module{
18709
18835
 
18710
18836
  this.dispatchExternal("rowDeselected", row.getComponent());
18711
18837
 
18712
- self._rowSelectionChanged(silent);
18838
+ self._rowSelectionChanged(silent, undefined, row);
18839
+
18840
+ return row;
18713
18841
  }
18714
18842
  }else {
18715
18843
  if(!silent){
@@ -18729,7 +18857,6 @@ class SelectRow extends Module{
18729
18857
  }
18730
18858
 
18731
18859
  getSelectedRows(){
18732
-
18733
18860
  var rows = [];
18734
18861
 
18735
18862
  this.selectedRows.forEach(function(row){
@@ -18739,7 +18866,7 @@ class SelectRow extends Module{
18739
18866
  return rows;
18740
18867
  }
18741
18868
 
18742
- _rowSelectionChanged(silent){
18869
+ _rowSelectionChanged(silent, selected = [], deselected = []){
18743
18870
  if(this.headerCheckboxElement){
18744
18871
  if(this.selectedRows.length === 0){
18745
18872
  this.headerCheckboxElement.checked = false;
@@ -18754,7 +18881,19 @@ class SelectRow extends Module{
18754
18881
  }
18755
18882
 
18756
18883
  if(!silent){
18757
- this.dispatchExternal("rowSelectionChanged", this.getSelectedData(), this.getSelectedRows());
18884
+ if(!Array.isArray(selected)){
18885
+ selected = [selected];
18886
+ }
18887
+
18888
+ selected = selected.map(row => row.getComponent());
18889
+
18890
+ if(!Array.isArray(deselected)){
18891
+ deselected = [deselected];
18892
+ }
18893
+
18894
+ deselected = deselected.map(row => row.getComponent());
18895
+
18896
+ this.dispatchExternal("rowSelectionChanged", this.getSelectedData(), this.getSelectedRows(), selected, deselected);
18758
18897
  }
18759
18898
  }
18760
18899
 
@@ -20443,14 +20582,21 @@ class BasicHorizontal extends Renderer{
20443
20582
  constructor(table){
20444
20583
  super(table);
20445
20584
  }
20446
-
20447
- renderRowCells(row){
20585
+
20586
+ renderRowCells(row, inFragment) {
20587
+ const rowFrag = document.createDocumentFragment();
20448
20588
  row.cells.forEach((cell) => {
20449
- row.element.appendChild(cell.getElement());
20450
- cell.cellRendered();
20589
+ rowFrag.appendChild(cell.getElement());
20451
20590
  });
20591
+ row.element.appendChild(rowFrag);
20592
+
20593
+ if(!inFragment){
20594
+ row.cells.forEach((cell) => {
20595
+ cell.cellRendered();
20596
+ });
20597
+ }
20452
20598
  }
20453
-
20599
+
20454
20600
  reinitializeColumnWidths(columns){
20455
20601
  columns.forEach(function(column){
20456
20602
  column.reinitializeWidth();
@@ -20631,8 +20777,13 @@ class VirtualDomHorizontal extends Renderer{
20631
20777
  if(this.initialized){
20632
20778
  this.initializeRow(row);
20633
20779
  }else {
20780
+ const rowFrag = document.createDocumentFragment();
20781
+ row.cells.forEach((cell) => {
20782
+ rowFrag.appendChild(cell.getElement());
20783
+ });
20784
+ row.element.appendChild(rowFrag);
20785
+
20634
20786
  row.cells.forEach((cell) => {
20635
- row.element.appendChild(cell.getElement());
20636
20787
  cell.cellRendered();
20637
20788
  });
20638
20789
  }
@@ -21067,6 +21218,8 @@ class ColumnManager extends CoreFeature {
21067
21218
 
21068
21219
  this.contentsElement.insertBefore(this.headersElement, this.contentsElement.firstChild);
21069
21220
  this.element.insertBefore(this.contentsElement, this.element.firstChild);
21221
+
21222
+ this.initializeScrollWheelWatcher();
21070
21223
 
21071
21224
  this.subscribe("scroll-horizontal", this.scrollHorizontal.bind(this));
21072
21225
  this.subscribe("scrollbar-vertical", this.padVerticalScrollbar.bind(this));
@@ -21158,6 +21311,19 @@ class ColumnManager extends CoreFeature {
21158
21311
 
21159
21312
  this.renderer.scrollColumns(left);
21160
21313
  }
21314
+
21315
+ initializeScrollWheelWatcher(){
21316
+ this.contentsElement.addEventListener("wheel", (e) => {
21317
+ var left;
21318
+
21319
+ if(e.deltaX){
21320
+ left = this.contentsElement.scrollLeft + e.deltaX;
21321
+
21322
+ this.table.rowManager.scrollHorizontal(left);
21323
+ this.table.columnManager.scrollHorizontal(left);
21324
+ }
21325
+ });
21326
+ }
21161
21327
 
21162
21328
  ///////////// Column Setup Functions /////////////
21163
21329
  generateColumnsFromRowData(data){
@@ -21759,79 +21925,100 @@ class ColumnManager extends CoreFeature {
21759
21925
  class BasicVertical extends Renderer{
21760
21926
  constructor(table){
21761
21927
  super(table);
21762
-
21928
+
21763
21929
  this.verticalFillMode = "fill";
21764
-
21930
+
21765
21931
  this.scrollTop = 0;
21766
21932
  this.scrollLeft = 0;
21767
-
21933
+
21768
21934
  this.scrollTop = 0;
21769
21935
  this.scrollLeft = 0;
21770
21936
  }
21771
-
21937
+
21772
21938
  clearRows(){
21773
21939
  var element = this.tableElement;
21774
-
21940
+
21775
21941
  // element.children.detach();
21776
21942
  while(element.firstChild) element.removeChild(element.firstChild);
21777
-
21943
+
21778
21944
  element.scrollTop = 0;
21779
21945
  element.scrollLeft = 0;
21780
-
21946
+
21781
21947
  element.style.minWidth = "";
21782
21948
  element.style.minHeight = "";
21783
21949
  element.style.display = "";
21784
21950
  element.style.visibility = "";
21785
21951
  }
21786
-
21787
- renderRows(){
21952
+
21953
+ renderRows() {
21788
21954
  var element = this.tableElement,
21789
- onlyGroupHeaders = true;
21790
-
21791
- this.rows().forEach((row, index) => {
21955
+ onlyGroupHeaders = true,
21956
+ tableFrag = document.createDocumentFragment(),
21957
+ rows = this.rows();
21958
+
21959
+ rows.forEach((row, index) => {
21792
21960
  this.styleRow(row, index);
21793
- element.appendChild(row.getElement());
21794
- row.initialize(true);
21795
-
21796
- if(row.type !== "group"){
21961
+ row.initialize(false, true);
21962
+
21963
+ if (row.type !== "group") {
21797
21964
  onlyGroupHeaders = false;
21798
21965
  }
21966
+
21967
+ tableFrag.appendChild(row.getElement());
21799
21968
  });
21800
-
21969
+
21970
+ element.appendChild(tableFrag);
21971
+
21972
+ rows.forEach((row) => {
21973
+ row.rendered();
21974
+
21975
+ if(!row.heightInitialized) {
21976
+ row.calcHeight(true);
21977
+ }
21978
+ });
21979
+
21980
+ rows.forEach((row) => {
21981
+ if(!row.heightInitialized) {
21982
+ row.setCellHeight();
21983
+ }
21984
+ });
21985
+
21986
+
21987
+
21801
21988
  if(onlyGroupHeaders){
21802
21989
  element.style.minWidth = this.table.columnManager.getWidth() + "px";
21803
21990
  }else {
21804
21991
  element.style.minWidth = "";
21805
21992
  }
21806
21993
  }
21807
-
21808
-
21994
+
21995
+
21809
21996
  rerenderRows(callback){
21810
21997
  this.clearRows();
21811
-
21998
+
21812
21999
  if(callback){
21813
22000
  callback();
21814
22001
  }
21815
-
22002
+
21816
22003
  this.renderRows();
21817
22004
  }
21818
-
22005
+
21819
22006
  scrollToRowNearestTop(row){
21820
22007
  var rowTop = Helpers.elOffset(row.getElement()).top;
21821
-
22008
+
21822
22009
  return !(Math.abs(this.elementVertical.scrollTop - rowTop) > Math.abs(this.elementVertical.scrollTop + this.elementVertical.clientHeight - rowTop));
21823
22010
  }
21824
-
22011
+
21825
22012
  scrollToRow(row){
21826
22013
  var rowEl = row.getElement();
21827
-
22014
+
21828
22015
  this.elementVertical.scrollTop = Helpers.elOffset(rowEl).top - Helpers.elOffset(this.elementVertical).top + this.elementVertical.scrollTop;
21829
22016
  }
21830
-
22017
+
21831
22018
  visibleRows(includingBuffer){
21832
22019
  return this.rows();
21833
22020
  }
21834
-
22021
+
21835
22022
  }
21836
22023
 
21837
22024
  class VirtualDomVertical extends Renderer{
@@ -21877,7 +22064,6 @@ class VirtualDomVertical extends Renderer{
21877
22064
 
21878
22065
  element.style.paddingTop = "";
21879
22066
  element.style.paddingBottom = "";
21880
- // element.style.minWidth = "";
21881
22067
  element.style.minHeight = "";
21882
22068
  element.style.display = "";
21883
22069
  element.style.visibility = "";
@@ -22056,17 +22242,27 @@ class VirtualDomVertical extends Renderer{
22056
22242
  //////////////////////////////////////
22057
22243
 
22058
22244
  //full virtual render
22059
- _virtualRenderFill(position, forceMove, offset){
22245
+ _virtualRenderFill(position, forceMove, offset) {
22060
22246
  var element = this.tableElement,
22061
22247
  holder = this.elementVertical,
22062
22248
  topPad = 0,
22063
22249
  rowsHeight = 0,
22250
+ rowHeight = 0,
22064
22251
  heightOccupied = 0,
22065
22252
  topPadHeight = 0,
22066
22253
  i = 0,
22067
22254
  rows = this.rows(),
22068
22255
  rowsCount = rows.length,
22069
- containerHeight = this.elementVertical.clientHeight;
22256
+ index = 0,
22257
+ row,
22258
+ rowFragment,
22259
+ renderedRows = [],
22260
+ totalRowsRendered = 0,
22261
+ rowsToRender = 0,
22262
+ fixedHeight = this.table.rowManager.fixedHeight,
22263
+ containerHeight = this.elementVertical.clientHeight,
22264
+ avgRowHeight = this.table.options.rowHeight,
22265
+ resized = true;
22070
22266
 
22071
22267
  position = position || 0;
22072
22268
 
@@ -22094,44 +22290,92 @@ class VirtualDomVertical extends Renderer{
22094
22290
 
22095
22291
  if(rowsCount && Helpers.elVisible(this.elementVertical)){
22096
22292
  this.vDomTop = position;
22097
-
22098
22293
  this.vDomBottom = position -1;
22099
22294
 
22100
- while ((rowsHeight <= containerHeight + this.vDomWindowBuffer || i < this.vDomWindowMinTotalRows) && this.vDomBottom < rowsCount -1){
22101
- var index = this.vDomBottom + 1,
22102
- row = rows[index],
22103
- rowHeight = 0;
22295
+ if(fixedHeight || this.table.options.maxHeight) {
22296
+ if(avgRowHeight) {
22297
+ rowsToRender = (containerHeight / avgRowHeight) + (this.vDomWindowBuffer / avgRowHeight);
22298
+ }
22299
+ rowsToRender = Math.max(this.vDomWindowMinTotalRows, Math.ceil(rowsToRender));
22300
+ }
22301
+ else {
22302
+ rowsToRender = rowsCount;
22303
+ }
22104
22304
 
22105
- this.styleRow(row, index);
22305
+ while(((rowsToRender == rowsCount || rowsHeight <= containerHeight + this.vDomWindowBuffer) || totalRowsRendered < this.vDomWindowMinTotalRows) && this.vDomBottom < rowsCount -1) {
22306
+ renderedRows = [];
22307
+ rowFragment = document.createDocumentFragment();
22106
22308
 
22107
- element.appendChild(row.getElement());
22309
+ i = 0;
22108
22310
 
22109
- row.initialize();
22311
+ while ((i < rowsToRender) && this.vDomBottom < rowsCount -1) {
22312
+ index = this.vDomBottom + 1,
22313
+ row = rows[index];
22110
22314
 
22111
- if(!row.heightInitialized){
22112
- row.normalizeHeight(true);
22113
- }
22315
+ this.styleRow(row, index);
22114
22316
 
22115
- rowHeight = row.getHeight();
22317
+ row.initialize(false, true);
22318
+ if(!row.heightInitialized && !this.table.options.rowHeight){
22319
+ row.clearCellHeight();
22320
+ }
22116
22321
 
22117
- if(i < topPad){
22118
- topPadHeight += rowHeight;
22119
- }else {
22120
- rowsHeight += rowHeight;
22322
+ rowFragment.appendChild(row.getElement());
22323
+ renderedRows.push(row);
22324
+ this.vDomBottom ++;
22325
+ i++;
22121
22326
  }
22122
22327
 
22123
- if(rowHeight > this.vDomWindowBuffer){
22124
- this.vDomWindowBuffer = rowHeight * 2;
22328
+ if(!renderedRows.length){
22329
+ break;
22125
22330
  }
22126
22331
 
22127
- this.vDomBottom ++;
22128
- i++;
22332
+ element.appendChild(rowFragment);
22333
+
22334
+ // NOTE: The next 3 loops are separate on purpose
22335
+ // This is to batch up the dom writes and reads which drastically improves performance
22336
+
22337
+ renderedRows.forEach((row) => {
22338
+ row.rendered();
22339
+
22340
+ if(!row.heightInitialized) {
22341
+ row.calcHeight(true);
22342
+ }
22343
+ });
22344
+
22345
+ renderedRows.forEach((row) => {
22346
+ if(!row.heightInitialized) {
22347
+ row.setCellHeight();
22348
+ }
22349
+ });
22350
+
22351
+ renderedRows.forEach((row) => {
22352
+ rowHeight = row.getHeight();
22353
+
22354
+ if(totalRowsRendered < topPad){
22355
+ topPadHeight += rowHeight;
22356
+ }else {
22357
+ rowsHeight += rowHeight;
22358
+ }
22359
+
22360
+ if(rowHeight > this.vDomWindowBuffer){
22361
+ this.vDomWindowBuffer = rowHeight * 2;
22362
+ }
22363
+ totalRowsRendered++;
22364
+ });
22365
+
22366
+ resized = this.table.rowManager.adjustTableSize();
22367
+ containerHeight = this.elementVertical.clientHeight;
22368
+ if(resized && (fixedHeight || this.table.options.maxHeight))
22369
+ {
22370
+ avgRowHeight = rowsHeight / totalRowsRendered;
22371
+ rowsToRender = Math.max(this.vDomWindowMinTotalRows, Math.ceil((containerHeight / avgRowHeight) + (this.vDomWindowBuffer / avgRowHeight)));
22372
+ }
22129
22373
  }
22130
22374
 
22131
22375
  if(!position){
22132
22376
  this.vDomTopPad = 0;
22133
22377
  //adjust row height to match average of rendered elements
22134
- this.vDomRowHeight = Math.floor((rowsHeight + topPadHeight) / i);
22378
+ this.vDomRowHeight = Math.floor((rowsHeight + topPadHeight) / totalRowsRendered);
22135
22379
  this.vDomBottomPad = this.vDomRowHeight * (rowsCount - this.vDomBottom -1);
22136
22380
 
22137
22381
  this.vDomScrollHeight = topPadHeight + rowsHeight + this.vDomBottomPad - containerHeight;
@@ -22139,9 +22383,9 @@ class VirtualDomVertical extends Renderer{
22139
22383
  this.vDomTopPad = !forceMove ? this.scrollTop - topPadHeight : (this.vDomRowHeight * this.vDomTop) + offset;
22140
22384
  this.vDomBottomPad = this.vDomBottom == rowsCount-1 ? 0 : Math.max(this.vDomScrollHeight - this.vDomTopPad - rowsHeight - topPadHeight, 0);
22141
22385
  }
22142
-
22143
- element.style.paddingTop = this.vDomTopPad + "px";
22144
- element.style.paddingBottom = this.vDomBottomPad + "px";
22386
+
22387
+ element.style.paddingTop = this.vDomTopPad+"px";
22388
+ element.style.paddingBottom = this.vDomBottomPad+"px";
22145
22389
 
22146
22390
  if(forceMove){
22147
22391
  this.scrollTop = this.vDomTopPad + (topPadHeight) + offset - (this.elementVertical.scrollWidth > this.elementVertical.clientWidth ? this.elementVertical.offsetHeight - containerHeight : 0);
@@ -22444,7 +22688,7 @@ class RowManager extends CoreFeature{
22444
22688
 
22445
22689
  this.dataPipeline = []; //hold data pipeline tasks
22446
22690
  this.displayPipeline = []; //hold data display pipeline tasks
22447
-
22691
+
22448
22692
  this.scrollbarWidth = 0;
22449
22693
 
22450
22694
  this.renderer = null;
@@ -22473,12 +22717,18 @@ class RowManager extends CoreFeature{
22473
22717
 
22474
22718
  initializePlaceholder(){
22475
22719
  var placeholder = this.table.options.placeholder;
22476
-
22720
+
22721
+ if(typeof placeholder === "function"){
22722
+ placeholder = placeholder.call(this.table);
22723
+ }
22724
+
22725
+ placeholder = this.chain("placeholder", [placeholder], placeholder, placeholder) || placeholder;
22726
+
22477
22727
  //configure placeholder element
22478
22728
  if(placeholder){
22479
22729
  let el = document.createElement("div");
22480
22730
  el.classList.add("tabulator-placeholder");
22481
-
22731
+
22482
22732
  if(typeof placeholder == "string"){
22483
22733
  let contents = document.createElement("div");
22484
22734
  contents.classList.add("tabulator-placeholder-contents");
@@ -22494,10 +22744,10 @@ class RowManager extends CoreFeature{
22494
22744
  this.placeholderContents = placeholder;
22495
22745
  }else {
22496
22746
  console.warn("Invalid placeholder provided, must be string or HTML Element", placeholder);
22497
-
22747
+
22498
22748
  this.el = null;
22499
22749
  }
22500
-
22750
+
22501
22751
  this.placeholder = el;
22502
22752
  }
22503
22753
  }
@@ -22658,15 +22908,15 @@ class RowManager extends CoreFeature{
22658
22908
  this.destroy();
22659
22909
 
22660
22910
  this.adjustTableSize();
22661
-
22911
+
22662
22912
  this.dispatch("rows-wiped");
22663
22913
  }
22664
-
22914
+
22665
22915
  destroy(){
22666
22916
  this.rows.forEach((row) => {
22667
22917
  row.wipe();
22668
22918
  });
22669
-
22919
+
22670
22920
  this.rows = [];
22671
22921
  this.activeRows = [];
22672
22922
  this.activeRowsPipeline = [];
@@ -22739,7 +22989,7 @@ class RowManager extends CoreFeature{
22739
22989
  rows.push(row);
22740
22990
  this.dispatch("row-added", row, item, pos, index);
22741
22991
  });
22742
-
22992
+
22743
22993
  this.refreshActiveData(refreshDisplayOnly ? "displayPipeline" : false, false, true);
22744
22994
 
22745
22995
  this.regenerateRowPositions();
@@ -23127,28 +23377,28 @@ class RowManager extends CoreFeature{
23127
23377
 
23128
23378
  for(let i = index; i < this.dataPipeline.length; i++){
23129
23379
  let result = this.dataPipeline[i].handler(this.activeRowsPipeline[i].slice(0));
23130
-
23380
+
23131
23381
  this.activeRowsPipeline[i + 1] = result || this.activeRowsPipeline[i].slice(0);
23132
23382
  }
23133
-
23383
+
23134
23384
  this.setActiveRows(this.activeRowsPipeline[this.dataPipeline.length]);
23135
-
23385
+
23136
23386
  case "display":
23137
23387
  index = 0;
23138
23388
  this.resetDisplayRows();
23139
-
23389
+
23140
23390
  case "displayPipeline":
23141
23391
  for(let i = index; i < this.displayPipeline.length; i++){
23142
23392
  let result = this.displayPipeline[i].handler((i ? this.getDisplayRows(i - 1) : this.activeRows).slice(0), renderInPosition);
23143
-
23393
+
23144
23394
  this.setDisplayRows(result || this.getDisplayRows(i - 1).slice(0), i);
23145
23395
  }
23146
23396
 
23147
23397
  case "end":
23148
- //case to handle scenario when trying to skip past end stage
23398
+ //case to handle scenario when trying to skip past end stage
23149
23399
  this.regenerateRowPositions();
23150
23400
  }
23151
-
23401
+
23152
23402
  if(this.getDisplayRows().length){
23153
23403
  this._clearPlaceholder();
23154
23404
  }
@@ -23184,7 +23434,7 @@ class RowManager extends CoreFeature{
23184
23434
  //set display row pipeline data
23185
23435
  setDisplayRows(displayRows, index){
23186
23436
  this.displayRows[index] = displayRows;
23187
-
23437
+
23188
23438
  if(index == this.displayRows.length -1){
23189
23439
  this.displayRowsCount = this.displayRows[this.displayRows.length -1].length;
23190
23440
  }
@@ -23219,7 +23469,7 @@ class RowManager extends CoreFeature{
23219
23469
  //return only actual rows (not group headers etc)
23220
23470
  getRows(type){
23221
23471
  var rows = [];
23222
-
23472
+
23223
23473
  switch(type){
23224
23474
  case "active":
23225
23475
  rows = this.activeRows;
@@ -23228,11 +23478,11 @@ class RowManager extends CoreFeature{
23228
23478
  case "display":
23229
23479
  rows = this.table.rowManager.getDisplayRows();
23230
23480
  break;
23231
-
23481
+
23232
23482
  case "visible":
23233
23483
  rows = this.getVisibleRows(false, true);
23234
23484
  break;
23235
-
23485
+
23236
23486
  default:
23237
23487
  rows = this.chain("rows-retrieve", type, null, this.rows) || this.rows;
23238
23488
  }
@@ -23253,25 +23503,25 @@ class RowManager extends CoreFeature{
23253
23503
  this.dispatchExternal("renderStarted");
23254
23504
 
23255
23505
  this.renderer.rerenderRows(callback);
23256
-
23506
+
23257
23507
  if(!this.fixedHeight){
23258
23508
  this.adjustTableSize();
23259
23509
  }
23260
-
23510
+
23261
23511
  this.scrollBarCheck();
23262
23512
 
23263
23513
  this.dispatchExternal("renderComplete");
23264
23514
  }
23265
23515
  }
23266
-
23516
+
23267
23517
  scrollBarCheck(){
23268
23518
  var scrollbarWidth = 0;
23269
-
23519
+
23270
23520
  //adjust for vertical scrollbar moving table when present
23271
23521
  if(this.element.scrollHeight > this.element.clientHeight){
23272
23522
  scrollbarWidth = this.element.offsetWidth - this.element.clientWidth;
23273
23523
  }
23274
-
23524
+
23275
23525
  if(scrollbarWidth !== this.scrollbarWidth){
23276
23526
  this.scrollbarWidth = scrollbarWidth;
23277
23527
  this.dispatch("scrollbar-vertical", scrollbarWidth);
@@ -23324,7 +23574,7 @@ class RowManager extends CoreFeature{
23324
23574
 
23325
23575
  if(this.firstRender){
23326
23576
  this.firstRender = false;
23327
-
23577
+
23328
23578
  if(!this.fixedHeight){
23329
23579
  this.adjustTableSize();
23330
23580
  }
@@ -23344,7 +23594,7 @@ class RowManager extends CoreFeature{
23344
23594
  if(!this.displayRowsCount){
23345
23595
  this._showPlaceholder();
23346
23596
  }
23347
-
23597
+
23348
23598
  this.scrollBarCheck();
23349
23599
 
23350
23600
  this.dispatchExternal("renderComplete");
@@ -23369,7 +23619,7 @@ class RowManager extends CoreFeature{
23369
23619
 
23370
23620
  this.renderer.clearRows();
23371
23621
  }
23372
-
23622
+
23373
23623
  tableEmpty(){
23374
23624
  this.renderEmptyScroll();
23375
23625
  this._showPlaceholder();
@@ -23377,10 +23627,18 @@ class RowManager extends CoreFeature{
23377
23627
 
23378
23628
  _showPlaceholder(){
23379
23629
  if(this.placeholder){
23630
+ if(this.placeholder && this.placeholder.parentNode){
23631
+ this.placeholder.parentNode.removeChild(this.placeholder);
23632
+ }
23633
+
23634
+ this.initializePlaceholder();
23635
+
23380
23636
  this.placeholder.setAttribute("tabulator-render-mode", this.renderMode);
23381
23637
 
23382
23638
  this.getElement().appendChild(this.placeholder);
23383
23639
  this._positionPlaceholder();
23640
+
23641
+ this.adjustTableSize();
23384
23642
  }
23385
23643
  }
23386
23644
 
@@ -23388,7 +23646,7 @@ class RowManager extends CoreFeature{
23388
23646
  if(this.placeholder && this.placeholder.parentNode){
23389
23647
  this.placeholder.parentNode.removeChild(this.placeholder);
23390
23648
  }
23391
-
23649
+
23392
23650
  // clear empty table placeholder min
23393
23651
  this.tableElement.style.minWidth = "";
23394
23652
  this.tableElement.style.display = "";
@@ -23423,7 +23681,8 @@ class RowManager extends CoreFeature{
23423
23681
 
23424
23682
  //adjust the height of the table holder to fit in the Tabulator element
23425
23683
  adjustTableSize(){
23426
- var initialHeight = this.element.clientHeight, minHeight;
23684
+ let initialHeight = this.element.clientHeight, minHeight;
23685
+ let resized = false;
23427
23686
 
23428
23687
  if(this.renderer.verticalFillMode === "fill"){
23429
23688
  let otherHeight = Math.floor(this.table.columnManager.getElement().getBoundingClientRect().height + (this.table.footerManager && this.table.footerManager.active && !this.table.footerManager.external ? this.table.footerManager.getElement().getBoundingClientRect().height : 0));
@@ -23431,12 +23690,14 @@ class RowManager extends CoreFeature{
23431
23690
  if(this.fixedHeight){
23432
23691
  minHeight = isNaN(this.table.options.minHeight) ? this.table.options.minHeight : this.table.options.minHeight + "px";
23433
23692
 
23693
+ const height = "calc(100% - " + otherHeight + "px)";
23434
23694
  this.element.style.minHeight = minHeight || "calc(100% - " + otherHeight + "px)";
23435
- this.element.style.height = "calc(100% - " + otherHeight + "px)";
23436
- this.element.style.maxHeight = "calc(100% - " + otherHeight + "px)";
23437
- }else {
23695
+ this.element.style.height = height;
23696
+ this.element.style.maxHeight = height;
23697
+ } else {
23438
23698
  this.element.style.height = "";
23439
- this.element.style.height = (this.table.element.clientHeight - otherHeight) + "px";
23699
+ this.element.style.height =
23700
+ this.table.element.clientHeight - otherHeight + "px";
23440
23701
  this.element.scrollTop = this.scrollTop;
23441
23702
  }
23442
23703
 
@@ -23444,17 +23705,19 @@ class RowManager extends CoreFeature{
23444
23705
 
23445
23706
  //check if the table has changed size when dealing with variable height tables
23446
23707
  if(!this.fixedHeight && initialHeight != this.element.clientHeight){
23708
+ resized = true;
23447
23709
  if(this.subscribed("table-resize")){
23448
23710
  this.dispatch("table-resize");
23449
23711
  }else {
23450
23712
  this.redraw();
23451
23713
  }
23452
23714
  }
23453
-
23715
+
23454
23716
  this.scrollBarCheck();
23455
23717
  }
23456
23718
 
23457
23719
  this._positionPlaceholder();
23720
+ return resized;
23458
23721
  }
23459
23722
 
23460
23723
  //reinitialize all rows
@@ -23489,15 +23752,14 @@ class RowManager extends CoreFeature{
23489
23752
 
23490
23753
  //redraw table
23491
23754
  redraw (force){
23492
- var left = this.scrollLeft;
23493
-
23494
- this.adjustTableSize();
23495
-
23755
+ const resized = this.adjustTableSize();
23496
23756
  this.table.tableWidth = this.table.element.clientWidth;
23497
23757
 
23498
23758
  if(!force){
23499
- this.reRenderInPosition();
23500
- this.scrollHorizontal(left);
23759
+ if(resized) {
23760
+ this.reRenderInPosition();
23761
+ }
23762
+ this.scrollHorizontal(this.scrollLeft);
23501
23763
  }else {
23502
23764
  this.renderTable();
23503
23765
  }
@@ -23974,58 +24236,66 @@ class ComponentFunctionBinder{
23974
24236
  class DataLoader extends CoreFeature{
23975
24237
  constructor(table){
23976
24238
  super(table);
23977
-
24239
+
23978
24240
  this.requestOrder = 0; //prevent requests coming out of sequence if overridden by another load request
23979
24241
  this.loading = false;
23980
24242
  }
23981
-
24243
+
23982
24244
  initialize(){}
23983
-
24245
+
23984
24246
  load(data, params, config, replace, silent, columnsChanged){
23985
24247
  var requestNo = ++this.requestOrder;
23986
24248
 
24249
+ if(this.table.destroyed){
24250
+ return Promise.resolve();
24251
+ }
24252
+
23987
24253
  this.dispatchExternal("dataLoading", data);
23988
-
24254
+
23989
24255
  //parse json data to array
23990
24256
  if (data && (data.indexOf("{") == 0 || data.indexOf("[") == 0)){
23991
24257
  data = JSON.parse(data);
23992
24258
  }
23993
-
24259
+
23994
24260
  if(this.confirm("data-loading", [data, params, config, silent])){
23995
24261
  this.loading = true;
23996
-
24262
+
23997
24263
  if(!silent){
23998
24264
  this.alertLoader();
23999
24265
  }
24000
-
24266
+
24001
24267
  //get params for request
24002
24268
  params = this.chain("data-params", [data, config, silent], params || {}, params || {});
24003
-
24269
+
24004
24270
  params = this.mapParams(params, this.table.options.dataSendParams);
24005
-
24271
+
24006
24272
  var result = this.chain("data-load", [data, params, config, silent], false, Promise.resolve([]));
24007
24273
 
24008
24274
  return result.then((response) => {
24009
- if(!Array.isArray(response) && typeof response == "object"){
24010
- response = this.mapParams(response, this.objectInvert(this.table.options.dataReceiveParams));
24011
- }
24012
-
24013
- var rowData = this.chain("data-loaded", response, null, response);
24014
-
24015
- if(requestNo == this.requestOrder){
24016
- this.clearAlert();
24017
-
24018
- if(rowData !== false){
24019
- this.dispatchExternal("dataLoaded", rowData);
24020
- this.table.rowManager.setData(rowData, replace, typeof columnsChanged === "undefined" ? !replace : columnsChanged);
24275
+ if(!this.table.destroyed){
24276
+ if(!Array.isArray(response) && typeof response == "object"){
24277
+ response = this.mapParams(response, this.objectInvert(this.table.options.dataReceiveParams));
24278
+ }
24279
+
24280
+ var rowData = this.chain("data-loaded", response, null, response);
24281
+
24282
+ if(requestNo == this.requestOrder){
24283
+ this.clearAlert();
24284
+
24285
+ if(rowData !== false){
24286
+ this.dispatchExternal("dataLoaded", rowData);
24287
+ this.table.rowManager.setData(rowData, replace, typeof columnsChanged === "undefined" ? !replace : columnsChanged);
24288
+ }
24289
+ }else {
24290
+ console.warn("Data Load Response Blocked - An active data load request was blocked by an attempt to change table data while the request was being made");
24021
24291
  }
24022
24292
  }else {
24023
- console.warn("Data Load Response Blocked - An active data load request was blocked by an attempt to change table data while the request was being made");
24293
+ console.warn("Data Load Response Blocked - Table has been destroyed");
24024
24294
  }
24025
24295
  }).catch((error) => {
24026
24296
  console.error("Data Load Error: ", error);
24027
24297
  this.dispatchExternal("dataLoadError", error);
24028
-
24298
+
24029
24299
  if(!silent){
24030
24300
  this.alertError();
24031
24301
  }
@@ -24039,52 +24309,52 @@ class DataLoader extends CoreFeature{
24039
24309
  });
24040
24310
  }else {
24041
24311
  this.dispatchExternal("dataLoaded", data);
24042
-
24312
+
24043
24313
  if(!data){
24044
24314
  data = [];
24045
24315
  }
24046
-
24316
+
24047
24317
  this.table.rowManager.setData(data, replace, typeof columnsChanged === "undefined" ? !replace : columnsChanged);
24048
24318
  return Promise.resolve();
24049
24319
  }
24050
24320
  }
24051
-
24321
+
24052
24322
  mapParams(params, map){
24053
24323
  var output = {};
24054
-
24324
+
24055
24325
  for(let key in params){
24056
24326
  output[map.hasOwnProperty(key) ? map[key] : key] = params[key];
24057
24327
  }
24058
-
24328
+
24059
24329
  return output;
24060
24330
  }
24061
-
24331
+
24062
24332
  objectInvert(obj){
24063
24333
  var output = {};
24064
-
24334
+
24065
24335
  for(let key in obj){
24066
24336
  output[obj[key]] = key;
24067
24337
  }
24068
-
24338
+
24069
24339
  return output;
24070
24340
  }
24071
-
24341
+
24072
24342
  blockActiveLoad(){
24073
24343
  this.requestOrder++;
24074
24344
  }
24075
-
24345
+
24076
24346
  alertLoader(){
24077
24347
  var shouldLoad = typeof this.table.options.dataLoader === "function" ? this.table.options.dataLoader() : this.table.options.dataLoader;
24078
-
24348
+
24079
24349
  if(shouldLoad){
24080
24350
  this.table.alertManager.alert(this.table.options.dataLoaderLoading || this.langText("data|loading"));
24081
24351
  }
24082
24352
  }
24083
-
24353
+
24084
24354
  alertError(){
24085
24355
  this.table.alertManager.alert(this.table.options.dataLoaderError || this.langText("data|error"), "error");
24086
24356
  }
24087
-
24357
+
24088
24358
  clearAlert(){
24089
24359
  this.table.alertManager.clear();
24090
24360
  }