tabulator-tables 5.4.4 → 5.5.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 (96) hide show
  1. package/bower.json +1 -1
  2. package/dist/css/tabulator.css +80 -48
  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 +89 -53
  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 +106 -68
  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 +110 -70
  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 +95 -57
  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 +93 -58
  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 +90 -54
  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 +96 -57
  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 +131 -75
  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 +80 -48
  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 +88 -52
  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 +363 -158
  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 +363 -158
  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 +1 -1
  55. package/src/js/core/ColumnManager.js +15 -0
  56. package/src/js/core/RowManager.js +57 -41
  57. package/src/js/core/cell/CellComponent.js +5 -3
  58. package/src/js/core/column/ColumnComponent.js +2 -2
  59. package/src/js/core/rendering/renderers/BasicHorizontal.js +7 -2
  60. package/src/js/core/rendering/renderers/BasicVertical.js +8 -5
  61. package/src/js/core/rendering/renderers/VirtualDomHorizontal.js +6 -1
  62. package/src/js/core/rendering/renderers/VirtualDomVertical.js +85 -31
  63. package/src/js/core/row/RowComponent.js +2 -2
  64. package/src/js/modules/ColumnCalcs/defaults/calculations.js +7 -0
  65. package/src/js/modules/DataTree/DataTree.js +1 -1
  66. package/src/js/modules/Download/defaults/downloaders/xlsx.js +5 -2
  67. package/src/js/modules/Edit/Edit.js +2 -3
  68. package/src/js/modules/Edit/List.js +14 -3
  69. package/src/js/modules/Edit/defaults/editors/date.js +1 -1
  70. package/src/js/modules/Edit/defaults/editors/datetime.js +1 -1
  71. package/src/js/modules/Edit/defaults/editors/input.js +1 -1
  72. package/src/js/modules/Edit/defaults/editors/number.js +1 -1
  73. package/src/js/modules/Edit/defaults/editors/range.js +1 -1
  74. package/src/js/modules/Edit/defaults/editors/textarea.js +1 -1
  75. package/src/js/modules/Edit/defaults/editors/tickCross.js +1 -1
  76. package/src/js/modules/Edit/defaults/editors/time.js +1 -1
  77. package/src/js/modules/Export/Export.js +3 -0
  78. package/src/js/modules/Filter/Filter.js +11 -0
  79. package/src/js/modules/Format/Format.js +3 -0
  80. package/src/js/modules/Format/defaults/formatters/money.js +9 -2
  81. package/src/js/modules/FrozenColumns/FrozenColumns.js +1 -1
  82. package/src/js/modules/GroupRows/GroupComponent.js +4 -0
  83. package/src/js/modules/Interaction/Interaction.js +12 -0
  84. package/src/js/modules/Persistence/Persistence.js +15 -1
  85. package/src/js/modules/ResponsiveLayout/ResponsiveLayout.js +3 -0
  86. package/src/js/modules/SelectRow/SelectRow.js +82 -54
  87. package/src/scss/tabulator.scss +82 -50
  88. package/src/scss/themes/bootstrap/tabulator_bootstrap3.scss +9 -5
  89. package/src/scss/themes/bootstrap/tabulator_bootstrap4.scss +27 -19
  90. package/src/scss/themes/bootstrap/tabulator_bootstrap5.scss +29 -19
  91. package/src/scss/themes/bulma/tabulator_bulma.scss +15 -9
  92. package/src/scss/themes/materialize/tabulator_materialize.scss +14 -10
  93. package/src/scss/themes/semanticui/tabulator_semanticui.scss +52 -27
  94. package/src/scss/themes/tabulator_midnight.scss +10 -6
  95. package/src/scss/themes/tabulator_modern.scss +16 -8
  96. package/src/scss/themes/tabulator_site.scss +8 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tabulator-tables",
3
- "version": "5.4.4",
3
+ "version": "5.5.0",
4
4
  "description": "Interactive table generation JavaScript library",
5
5
  "style": "dist/css/tabulator.css",
6
6
  "main": "dist/js/tabulator.js",
@@ -41,6 +41,8 @@ export default class ColumnManager extends CoreFeature {
41
41
 
42
42
  this.contentsElement.insertBefore(this.headersElement, this.contentsElement.firstChild);
43
43
  this.element.insertBefore(this.contentsElement, this.element.firstChild);
44
+
45
+ this.initializeScrollWheelWatcher();
44
46
 
45
47
  this.subscribe("scroll-horizontal", this.scrollHorizontal.bind(this));
46
48
  this.subscribe("scrollbar-vertical", this.padVerticalScrollbar.bind(this));
@@ -132,6 +134,19 @@ export default class ColumnManager extends CoreFeature {
132
134
 
133
135
  this.renderer.scrollColumns(left);
134
136
  }
137
+
138
+ initializeScrollWheelWatcher(){
139
+ this.contentsElement.addEventListener("wheel", (e) => {
140
+ var left;
141
+
142
+ if(e.deltaX){
143
+ left = this.contentsElement.scrollLeft + e.deltaX;
144
+
145
+ this.table.rowManager.scrollHorizontal(left);
146
+ this.table.columnManager.scrollHorizontal(left);
147
+ }
148
+ });
149
+ }
135
150
 
136
151
  ///////////// Column Setup Functions /////////////
137
152
  generateColumnsFromRowData(data){
@@ -38,7 +38,7 @@ export default class RowManager extends CoreFeature{
38
38
 
39
39
  this.dataPipeline = []; //hold data pipeline tasks
40
40
  this.displayPipeline = []; //hold data display pipeline tasks
41
-
41
+
42
42
  this.scrollbarWidth = 0;
43
43
 
44
44
  this.renderer = null;
@@ -67,12 +67,18 @@ export default class RowManager extends CoreFeature{
67
67
 
68
68
  initializePlaceholder(){
69
69
  var placeholder = this.table.options.placeholder;
70
-
70
+
71
+ if(typeof placeholder === "function"){
72
+ placeholder = placeholder.call(this.table);
73
+ }
74
+
75
+ placeholder = this.chain("placeholder", [placeholder], placeholder, placeholder) || placeholder;
76
+
71
77
  //configure placeholder element
72
78
  if(placeholder){
73
79
  let el = document.createElement("div");
74
80
  el.classList.add("tabulator-placeholder");
75
-
81
+
76
82
  if(typeof placeholder == "string"){
77
83
  let contents = document.createElement("div");
78
84
  contents.classList.add("tabulator-placeholder-contents");
@@ -88,10 +94,10 @@ export default class RowManager extends CoreFeature{
88
94
  this.placeholderContents = placeholder;
89
95
  }else{
90
96
  console.warn("Invalid placeholder provided, must be string or HTML Element", placeholder);
91
-
97
+
92
98
  this.el = null;
93
99
  }
94
-
100
+
95
101
  this.placeholder = el;
96
102
  }
97
103
  }
@@ -252,15 +258,15 @@ export default class RowManager extends CoreFeature{
252
258
  this.destroy();
253
259
 
254
260
  this.adjustTableSize();
255
-
261
+
256
262
  this.dispatch("rows-wiped");
257
263
  }
258
-
264
+
259
265
  destroy(){
260
266
  this.rows.forEach((row) => {
261
267
  row.wipe();
262
268
  });
263
-
269
+
264
270
  this.rows = [];
265
271
  this.activeRows = [];
266
272
  this.activeRowsPipeline = [];
@@ -333,7 +339,7 @@ export default class RowManager extends CoreFeature{
333
339
  rows.push(row);
334
340
  this.dispatch("row-added", row, item, pos, index);
335
341
  });
336
-
342
+
337
343
  this.refreshActiveData(refreshDisplayOnly ? "displayPipeline" : false, false, true);
338
344
 
339
345
  this.regenerateRowPositions();
@@ -721,28 +727,28 @@ export default class RowManager extends CoreFeature{
721
727
 
722
728
  for(let i = index; i < this.dataPipeline.length; i++){
723
729
  let result = this.dataPipeline[i].handler(this.activeRowsPipeline[i].slice(0));
724
-
730
+
725
731
  this.activeRowsPipeline[i + 1] = result || this.activeRowsPipeline[i].slice(0);
726
732
  }
727
-
733
+
728
734
  this.setActiveRows(this.activeRowsPipeline[this.dataPipeline.length]);
729
-
735
+
730
736
  case "display":
731
737
  index = 0;
732
738
  this.resetDisplayRows();
733
-
739
+
734
740
  case "displayPipeline":
735
741
  for(let i = index; i < this.displayPipeline.length; i++){
736
742
  let result = this.displayPipeline[i].handler((i ? this.getDisplayRows(i - 1) : this.activeRows).slice(0), renderInPosition);
737
-
743
+
738
744
  this.setDisplayRows(result || this.getDisplayRows(i - 1).slice(0), i);
739
745
  }
740
746
 
741
747
  case "end":
742
- //case to handle scenario when trying to skip past end stage
748
+ //case to handle scenario when trying to skip past end stage
743
749
  this.regenerateRowPositions();
744
750
  }
745
-
751
+
746
752
  if(this.getDisplayRows().length){
747
753
  this._clearPlaceholder();
748
754
  }
@@ -778,7 +784,7 @@ export default class RowManager extends CoreFeature{
778
784
  //set display row pipeline data
779
785
  setDisplayRows(displayRows, index){
780
786
  this.displayRows[index] = displayRows;
781
-
787
+
782
788
  if(index == this.displayRows.length -1){
783
789
  this.displayRowsCount = this.displayRows[this.displayRows.length -1].length;
784
790
  }
@@ -813,7 +819,7 @@ export default class RowManager extends CoreFeature{
813
819
  //return only actual rows (not group headers etc)
814
820
  getRows(type){
815
821
  var rows = [];
816
-
822
+
817
823
  switch(type){
818
824
  case "active":
819
825
  rows = this.activeRows;
@@ -822,11 +828,11 @@ export default class RowManager extends CoreFeature{
822
828
  case "display":
823
829
  rows = this.table.rowManager.getDisplayRows();
824
830
  break;
825
-
831
+
826
832
  case "visible":
827
833
  rows = this.getVisibleRows(false, true);
828
834
  break;
829
-
835
+
830
836
  default:
831
837
  rows = this.chain("rows-retrieve", type, null, this.rows) || this.rows;
832
838
  }
@@ -847,25 +853,25 @@ export default class RowManager extends CoreFeature{
847
853
  this.dispatchExternal("renderStarted");
848
854
 
849
855
  this.renderer.rerenderRows(callback);
850
-
856
+
851
857
  if(!this.fixedHeight){
852
858
  this.adjustTableSize();
853
859
  }
854
-
860
+
855
861
  this.scrollBarCheck();
856
862
 
857
863
  this.dispatchExternal("renderComplete");
858
864
  }
859
865
  }
860
-
866
+
861
867
  scrollBarCheck(){
862
868
  var scrollbarWidth = 0;
863
-
869
+
864
870
  //adjust for vertical scrollbar moving table when present
865
871
  if(this.element.scrollHeight > this.element.clientHeight){
866
872
  scrollbarWidth = this.element.offsetWidth - this.element.clientWidth;
867
873
  }
868
-
874
+
869
875
  if(scrollbarWidth !== this.scrollbarWidth){
870
876
  this.scrollbarWidth = scrollbarWidth;
871
877
  this.dispatch("scrollbar-vertical", scrollbarWidth);
@@ -918,7 +924,7 @@ export default class RowManager extends CoreFeature{
918
924
 
919
925
  if(this.firstRender){
920
926
  this.firstRender = false;
921
-
927
+
922
928
  if(!this.fixedHeight){
923
929
  this.adjustTableSize();
924
930
  }
@@ -938,7 +944,7 @@ export default class RowManager extends CoreFeature{
938
944
  if(!this.displayRowsCount){
939
945
  this._showPlaceholder();
940
946
  }
941
-
947
+
942
948
  this.scrollBarCheck();
943
949
 
944
950
  this.dispatchExternal("renderComplete");
@@ -963,7 +969,7 @@ export default class RowManager extends CoreFeature{
963
969
 
964
970
  this.renderer.clearRows();
965
971
  }
966
-
972
+
967
973
  tableEmpty(){
968
974
  this.renderEmptyScroll();
969
975
  this._showPlaceholder();
@@ -971,6 +977,12 @@ export default class RowManager extends CoreFeature{
971
977
 
972
978
  _showPlaceholder(){
973
979
  if(this.placeholder){
980
+ if(this.placeholder && this.placeholder.parentNode){
981
+ this.placeholder.parentNode.removeChild(this.placeholder);
982
+ }
983
+
984
+ this.initializePlaceholder();
985
+
974
986
  this.placeholder.setAttribute("tabulator-render-mode", this.renderMode);
975
987
 
976
988
  this.getElement().appendChild(this.placeholder);
@@ -982,7 +994,7 @@ export default class RowManager extends CoreFeature{
982
994
  if(this.placeholder && this.placeholder.parentNode){
983
995
  this.placeholder.parentNode.removeChild(this.placeholder);
984
996
  }
985
-
997
+
986
998
  // clear empty table placeholder min
987
999
  this.tableElement.style.minWidth = "";
988
1000
  this.tableElement.style.display = "";
@@ -1017,7 +1029,8 @@ export default class RowManager extends CoreFeature{
1017
1029
 
1018
1030
  //adjust the height of the table holder to fit in the Tabulator element
1019
1031
  adjustTableSize(){
1020
- var initialHeight = this.element.clientHeight, minHeight;
1032
+ let initialHeight = this.element.clientHeight, minHeight;
1033
+ let resized = false;
1021
1034
 
1022
1035
  if(this.renderer.verticalFillMode === "fill"){
1023
1036
  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));
@@ -1025,12 +1038,14 @@ export default class RowManager extends CoreFeature{
1025
1038
  if(this.fixedHeight){
1026
1039
  minHeight = isNaN(this.table.options.minHeight) ? this.table.options.minHeight : this.table.options.minHeight + "px";
1027
1040
 
1041
+ const height = "calc(100% - " + otherHeight + "px)";
1028
1042
  this.element.style.minHeight = minHeight || "calc(100% - " + otherHeight + "px)";
1029
- this.element.style.height = "calc(100% - " + otherHeight + "px)";
1030
- this.element.style.maxHeight = "calc(100% - " + otherHeight + "px)";
1031
- }else{
1043
+ this.element.style.height = height;
1044
+ this.element.style.maxHeight = height;
1045
+ } else {
1032
1046
  this.element.style.height = "";
1033
- this.element.style.height = (this.table.element.clientHeight - otherHeight) + "px";
1047
+ this.element.style.height =
1048
+ this.table.element.clientHeight - otherHeight + "px";
1034
1049
  this.element.scrollTop = this.scrollTop;
1035
1050
  }
1036
1051
 
@@ -1038,17 +1053,19 @@ export default class RowManager extends CoreFeature{
1038
1053
 
1039
1054
  //check if the table has changed size when dealing with variable height tables
1040
1055
  if(!this.fixedHeight && initialHeight != this.element.clientHeight){
1056
+ resized = true;
1041
1057
  if(this.subscribed("table-resize")){
1042
1058
  this.dispatch("table-resize");
1043
1059
  }else{
1044
1060
  this.redraw();
1045
1061
  }
1046
1062
  }
1047
-
1063
+
1048
1064
  this.scrollBarCheck();
1049
1065
  }
1050
1066
 
1051
1067
  this._positionPlaceholder();
1068
+ return resized;
1052
1069
  }
1053
1070
 
1054
1071
  //reinitialize all rows
@@ -1083,15 +1100,14 @@ export default class RowManager extends CoreFeature{
1083
1100
 
1084
1101
  //redraw table
1085
1102
  redraw (force){
1086
- var left = this.scrollLeft;
1087
-
1088
- this.adjustTableSize();
1089
-
1103
+ const resized = this.adjustTableSize();
1090
1104
  this.table.tableWidth = this.table.element.clientWidth;
1091
1105
 
1092
1106
  if(!force){
1093
- this.reRenderInPosition();
1094
- this.scrollHorizontal(left);
1107
+ if(resized) {
1108
+ this.reRenderInPosition();
1109
+ }
1110
+ this.scrollHorizontal(this.scrollLeft);
1095
1111
  }else{
1096
1112
  this.renderTable();
1097
1113
  }
@@ -35,10 +35,12 @@ export default class CellComponent {
35
35
  return this._cell.row.getComponent();
36
36
  }
37
37
 
38
- getData(){
39
- return this._cell.row.getData();
38
+ getData(transform){
39
+ return this._cell.row.getData(transform);
40
+ }
41
+ getType(){
42
+ return "cell";
40
43
  }
41
-
42
44
  getField(){
43
45
  return this._cell.column.getField();
44
46
  }
@@ -99,8 +99,8 @@ export default class ColumnComponent {
99
99
  return this._column;
100
100
  }
101
101
 
102
- scrollTo(){
103
- return this._column.table.columnManager.scrollToColumn(this._column);
102
+ scrollTo(position, ifVisible){
103
+ return this._column.table.columnManager.scrollToColumn(this._column, position, ifVisible);
104
104
  }
105
105
 
106
106
  getTable(){
@@ -5,9 +5,14 @@ export default class BasicHorizontal extends Renderer{
5
5
  super(table);
6
6
  }
7
7
 
8
- renderRowCells(row){
8
+ renderRowCells(row) {
9
+ const rowFrag = document.createDocumentFragment();
10
+ row.cells.forEach((cell) => {
11
+ rowFrag.appendChild(cell.getElement());
12
+ });
13
+ row.element.appendChild(rowFrag);
14
+
9
15
  row.cells.forEach((cell) => {
10
- row.element.appendChild(cell.getElement());
11
16
  cell.cellRendered();
12
17
  });
13
18
  }
@@ -29,19 +29,22 @@ export default class BasicVertical extends Renderer{
29
29
  element.style.visibility = "";
30
30
  }
31
31
 
32
- renderRows(){
32
+ renderRows() {
33
33
  var element = this.tableElement,
34
- onlyGroupHeaders = true;
34
+ onlyGroupHeaders = true,
35
+ tableFrag = document.createDocumentFragment();
35
36
 
36
37
  this.rows().forEach((row, index) => {
37
38
  this.styleRow(row, index);
38
- element.appendChild(row.getElement());
39
39
  row.initialize(true);
40
40
 
41
- if(row.type !== "group"){
41
+ if (row.type !== "group") {
42
42
  onlyGroupHeaders = false;
43
43
  }
44
+
45
+ tableFrag.appendChild(row.getElement());
44
46
  });
47
+ element.appendChild(tableFrag);
45
48
 
46
49
  if(onlyGroupHeaders){
47
50
  element.style.minWidth = this.table.columnManager.getWidth() + "px";
@@ -77,4 +80,4 @@ export default class BasicVertical extends Renderer{
77
80
  return this.rows();
78
81
  }
79
82
 
80
- }
83
+ }
@@ -173,8 +173,13 @@ export default class VirtualDomHorizontal extends Renderer{
173
173
  if(this.initialized){
174
174
  this.initializeRow(row);
175
175
  }else{
176
+ const rowFrag = document.createDocumentFragment();
177
+ row.cells.forEach((cell) => {
178
+ rowFrag.appendChild(cell.getElement());
179
+ });
180
+ row.element.appendChild(rowFrag);
181
+
176
182
  row.cells.forEach((cell) => {
177
- row.element.appendChild(cell.getElement());
178
183
  cell.cellRendered();
179
184
  });
180
185
  }
@@ -44,7 +44,6 @@ export default class VirtualDomVertical extends Renderer{
44
44
 
45
45
  element.style.paddingTop = "";
46
46
  element.style.paddingBottom = "";
47
- // element.style.minWidth = "";
48
47
  element.style.minHeight = "";
49
48
  element.style.display = "";
50
49
  element.style.visibility = "";
@@ -223,17 +222,27 @@ export default class VirtualDomVertical extends Renderer{
223
222
  //////////////////////////////////////
224
223
 
225
224
  //full virtual render
226
- _virtualRenderFill(position, forceMove, offset){
225
+ _virtualRenderFill(position, forceMove, offset) {
227
226
  var element = this.tableElement,
228
227
  holder = this.elementVertical,
229
228
  topPad = 0,
230
229
  rowsHeight = 0,
230
+ rowHeight = 0,
231
231
  heightOccupied = 0,
232
232
  topPadHeight = 0,
233
233
  i = 0,
234
234
  rows = this.rows(),
235
235
  rowsCount = rows.length,
236
- containerHeight = this.elementVertical.clientHeight;
236
+ index = 0,
237
+ row,
238
+ rowFragment,
239
+ renderedRows = [],
240
+ totalRowsRendered = 0,
241
+ rowsToRender = 0,
242
+ fixedHeight = this.table.rowManager.fixedHeight,
243
+ containerHeight = this.elementVertical.clientHeight,
244
+ avgRowHeight = this.table.options.rowHeight,
245
+ resized = true;
237
246
 
238
247
  position = position || 0;
239
248
 
@@ -241,7 +250,7 @@ export default class VirtualDomVertical extends Renderer{
241
250
 
242
251
  if(!position){
243
252
  this.clear();
244
- }else{
253
+ }else {
245
254
  while(element.firstChild) element.removeChild(element.firstChild);
246
255
 
247
256
  //check if position is too close to bottom of table
@@ -261,54 +270,99 @@ export default class VirtualDomVertical extends Renderer{
261
270
 
262
271
  if(rowsCount && Helpers.elVisible(this.elementVertical)){
263
272
  this.vDomTop = position;
264
-
265
273
  this.vDomBottom = position -1;
266
274
 
267
- while ((rowsHeight <= containerHeight + this.vDomWindowBuffer || i < this.vDomWindowMinTotalRows) && this.vDomBottom < rowsCount -1){
268
- var index = this.vDomBottom + 1,
269
- row = rows[index],
270
- rowHeight = 0;
271
-
272
- this.styleRow(row, index);
275
+ if(fixedHeight || this.table.options.maxHeight) {
276
+ if(avgRowHeight) {
277
+ rowsToRender = (containerHeight / avgRowHeight) + (this.vDomWindowBuffer / avgRowHeight);
278
+ }
279
+ rowsToRender = Math.max(this.vDomWindowMinTotalRows, Math.ceil(rowsToRender));
280
+ }
281
+ else {
282
+ rowsToRender = rowsCount;
283
+ }
273
284
 
274
- element.appendChild(row.getElement());
285
+ while(((rowsToRender == rowsCount || rowsHeight <= containerHeight + this.vDomWindowBuffer) || totalRowsRendered < this.vDomWindowMinTotalRows) && this.vDomBottom < rowsCount -1) {
286
+ renderedRows = [];
287
+ rowFragment = document.createDocumentFragment();
275
288
 
276
- row.initialize();
289
+ i = 0;
290
+ while ((i < rowsToRender) && this.vDomBottom < rowsCount -1) {
291
+ index = this.vDomBottom + 1,
292
+ row = rows[index];
277
293
 
278
- if(!row.heightInitialized){
279
- row.normalizeHeight(true);
280
- }
294
+ this.styleRow(row, index);
281
295
 
282
- rowHeight = row.getHeight();
296
+ row.initialize();
297
+ if(!row.heightInitialized && !this.table.options.rowHeight){
298
+ row.clearCellHeight();
299
+ }
283
300
 
284
- if(i < topPad){
285
- topPadHeight += rowHeight;
286
- }else{
287
- rowsHeight += rowHeight;
301
+ rowFragment.appendChild(row.getElement());
302
+ renderedRows.push(row);
303
+ this.vDomBottom ++;
304
+ i++;
288
305
  }
289
306
 
290
- if(rowHeight > this.vDomWindowBuffer){
291
- this.vDomWindowBuffer = rowHeight * 2;
307
+ if(!renderedRows.length){
308
+ break;
292
309
  }
310
+ element.appendChild(rowFragment);
311
+
312
+ // NOTE: The next 3 loops are separate on purpose
313
+ // This is to batch up the dom writes and reads which drastically improves performance
314
+ renderedRows.forEach((row) => {
315
+ if(!row.heightInitialized) {
316
+ row.calcHeight(true);
317
+
318
+ }
319
+ });
320
+
321
+ renderedRows.forEach((row) => {
322
+ if(!row.heightInitialized) {
323
+ row.setCellHeight();
324
+
325
+ }
326
+ });
327
+
328
+ renderedRows.forEach((row) => {
329
+ rowHeight = row.getHeight();
330
+
331
+ if(totalRowsRendered < topPad){
332
+ topPadHeight += rowHeight;
333
+ }else {
334
+ rowsHeight += rowHeight;
335
+ }
293
336
 
294
- this.vDomBottom ++;
295
- i++;
337
+ if(rowHeight > this.vDomWindowBuffer){
338
+ this.vDomWindowBuffer = rowHeight * 2;
339
+ }
340
+ totalRowsRendered++;
341
+ });
342
+
343
+ resized = this.table.rowManager.adjustTableSize();
344
+ containerHeight = this.elementVertical.clientHeight;
345
+ if(resized && (fixedHeight || this.table.options.maxHeight))
346
+ {
347
+ avgRowHeight = rowsHeight / totalRowsRendered;
348
+ rowsToRender = Math.max(this.vDomWindowMinTotalRows, Math.ceil((containerHeight / avgRowHeight) + (this.vDomWindowBuffer / avgRowHeight)));
349
+ }
296
350
  }
297
351
 
298
352
  if(!position){
299
353
  this.vDomTopPad = 0;
300
354
  //adjust row height to match average of rendered elements
301
- this.vDomRowHeight = Math.floor((rowsHeight + topPadHeight) / i);
355
+ this.vDomRowHeight = Math.floor((rowsHeight + topPadHeight) / totalRowsRendered);
302
356
  this.vDomBottomPad = this.vDomRowHeight * (rowsCount - this.vDomBottom -1);
303
357
 
304
358
  this.vDomScrollHeight = topPadHeight + rowsHeight + this.vDomBottomPad - containerHeight;
305
- }else{
359
+ }else {
306
360
  this.vDomTopPad = !forceMove ? this.scrollTop - topPadHeight : (this.vDomRowHeight * this.vDomTop) + offset;
307
361
  this.vDomBottomPad = this.vDomBottom == rowsCount-1 ? 0 : Math.max(this.vDomScrollHeight - this.vDomTopPad - rowsHeight - topPadHeight, 0);
308
362
  }
309
-
310
- element.style.paddingTop = this.vDomTopPad + "px";
311
- element.style.paddingBottom = this.vDomBottomPad + "px";
363
+
364
+ element.style.paddingTop = this.vDomTopPad+"px";
365
+ element.style.paddingBottom = this.vDomBottomPad+"px";
312
366
 
313
367
  if(forceMove){
314
368
  this.scrollTop = this.vDomTopPad + (topPadHeight) + offset - (this.elementVertical.scrollWidth > this.elementVertical.clientWidth ? this.elementVertical.offsetHeight - containerHeight : 0);
@@ -577,4 +631,4 @@ export default class VirtualDomVertical extends Renderer{
577
631
  row.setCellHeight();
578
632
  }
579
633
  }
580
- }
634
+ }
@@ -54,8 +54,8 @@ export default class RowComponent {
54
54
  return this._row.delete();
55
55
  }
56
56
 
57
- scrollTo(){
58
- return this._row.table.rowManager.scrollToRow(this._row);
57
+ scrollTo(position, ifVisible){
58
+ return this._row.table.rowManager.scrollToRow(this._row, position, ifVisible);
59
59
  }
60
60
 
61
61
  move(to, after){
@@ -83,4 +83,11 @@ export default {
83
83
 
84
84
  return output;
85
85
  },
86
+ "unique":function(values, data, calcParams){
87
+ var unique = values.filter((value, index) => {
88
+ return (values || value === 0) && values.indexOf(value) === index;
89
+ });
90
+
91
+ return unique.length;
92
+ },
86
93
  };
@@ -305,7 +305,7 @@ class DataTree extends Module{
305
305
 
306
306
  row.create();
307
307
 
308
- config = row.modules.dataTree.children;
308
+ config = row.modules.dataTree;
309
309
 
310
310
  if(!config.index && config.children !== false){
311
311
  children = this.getChildren(row);
@@ -6,8 +6,11 @@ export default function(list, options, setFileContents){
6
6
  workbook = XLSX.utils.book_new(),
7
7
  tableFeatures = new CoreFeature(this),
8
8
  compression = 'compress' in options ? options.compress : true,
9
+ writeOptions = options.writeOptions || {bookType:'xlsx', bookSST:true, compression},
9
10
  output;
10
11
 
12
+ writeOptions.type = 'binary';
13
+
11
14
  workbook.SheetNames = [];
12
15
  workbook.Sheets = {};
13
16
 
@@ -93,7 +96,7 @@ export default function(list, options, setFileContents){
93
96
  return buf;
94
97
  }
95
98
 
96
- output = XLSX.write(workbook, {bookType:'xlsx', bookSST:true, type: 'binary', compression });
99
+ output = XLSX.write(workbook, writeOptions);
97
100
 
98
101
  setFileContents(s2ab(output), "application/octet-stream");
99
- }
102
+ }
@@ -514,8 +514,8 @@ class Edit extends Module{
514
514
  cellEl = cell.getElement();
515
515
 
516
516
  if(this.table.modExists("frozenColumns")){
517
- leftEdge += parseInt(this.table.modules.frozenColumns.leftMargin);
518
- rightEdge -= parseInt(this.table.modules.frozenColumns.rightMargin);
517
+ leftEdge += parseInt(this.table.modules.frozenColumns.leftMargin || 0);
518
+ rightEdge -= parseInt(this.table.modules.frozenColumns.rightMargin || 0);
519
519
  }
520
520
 
521
521
  if(this.table.options.renderHorizontal === "virtual"){
@@ -524,7 +524,6 @@ class Edit extends Module{
524
524
  }
525
525
 
526
526
  if(cellEl.offsetLeft < leftEdge){
527
-
528
527
  this.table.rowManager.element.scrollLeft -= (leftEdge - cellEl.offsetLeft);
529
528
  }else{
530
529
  if(cellEl.offsetLeft + cellEl.offsetWidth > rightEdge){