tabulator-tables 5.4.3 → 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 (253) hide show
  1. package/.babelrc.json +3 -3
  2. package/.editorconfig +6 -6
  3. package/.eslintignore +3 -3
  4. package/.eslintrc.js +28 -28
  5. package/.github/ISSUE_TEMPLATE/bug_report.md +58 -58
  6. package/.github/ISSUE_TEMPLATE/documentation.md +14 -14
  7. package/.github/ISSUE_TEMPLATE/feature_request.md +24 -24
  8. package/.github/ISSUE_TEMPLATE/question.md +12 -12
  9. package/.github/workflows/bad-files-check.yml +39 -39
  10. package/.github/workflows/lint-and-test.yml +30 -30
  11. package/CODE_OF_CONDUCT.md +46 -46
  12. package/CONTRIBUTING.md +22 -22
  13. package/LICENSE +20 -20
  14. package/README.md +76 -76
  15. package/bower.json +40 -40
  16. package/build/Bundler.js +185 -185
  17. package/build/rollup.js +6 -6
  18. package/dist/css/tabulator.css +80 -53
  19. package/dist/css/tabulator.css.map +1 -1
  20. package/dist/css/tabulator.min.css +1 -1
  21. package/dist/css/tabulator.min.css.map +1 -1
  22. package/dist/css/tabulator_bootstrap3.css +89 -58
  23. package/dist/css/tabulator_bootstrap3.css.map +1 -1
  24. package/dist/css/tabulator_bootstrap3.min.css +1 -1
  25. package/dist/css/tabulator_bootstrap3.min.css.map +1 -1
  26. package/dist/css/tabulator_bootstrap4.css +106 -73
  27. package/dist/css/tabulator_bootstrap4.css.map +1 -1
  28. package/dist/css/tabulator_bootstrap4.min.css +1 -1
  29. package/dist/css/tabulator_bootstrap4.min.css.map +1 -1
  30. package/dist/css/tabulator_bootstrap5.css +110 -75
  31. package/dist/css/tabulator_bootstrap5.css.map +1 -1
  32. package/dist/css/tabulator_bootstrap5.min.css +1 -1
  33. package/dist/css/tabulator_bootstrap5.min.css.map +1 -1
  34. package/dist/css/tabulator_bulma.css +95 -62
  35. package/dist/css/tabulator_bulma.css.map +1 -1
  36. package/dist/css/tabulator_bulma.min.css +1 -1
  37. package/dist/css/tabulator_bulma.min.css.map +1 -1
  38. package/dist/css/tabulator_materialize.css +93 -63
  39. package/dist/css/tabulator_materialize.css.map +1 -1
  40. package/dist/css/tabulator_materialize.min.css +1 -1
  41. package/dist/css/tabulator_materialize.min.css.map +1 -1
  42. package/dist/css/tabulator_midnight.css +90 -59
  43. package/dist/css/tabulator_midnight.css.map +1 -1
  44. package/dist/css/tabulator_midnight.min.css +1 -1
  45. package/dist/css/tabulator_midnight.min.css.map +1 -1
  46. package/dist/css/tabulator_modern.css +96 -62
  47. package/dist/css/tabulator_modern.css.map +1 -1
  48. package/dist/css/tabulator_modern.min.css +1 -1
  49. package/dist/css/tabulator_modern.min.css.map +1 -1
  50. package/dist/css/tabulator_semanticui.css +233 -182
  51. package/dist/css/tabulator_semanticui.css.map +1 -1
  52. package/dist/css/tabulator_semanticui.min.css +1 -1
  53. package/dist/css/tabulator_semanticui.min.css.map +1 -1
  54. package/dist/css/tabulator_simple.css +80 -53
  55. package/dist/css/tabulator_simple.css.map +1 -1
  56. package/dist/css/tabulator_simple.min.css +1 -1
  57. package/dist/css/tabulator_simple.min.css.map +1 -1
  58. package/dist/css/tabulator_site.css +88 -57
  59. package/dist/css/tabulator_site.css.map +1 -1
  60. package/dist/css/tabulator_site.min.css +1 -1
  61. package/dist/css/tabulator_site.min.css.map +1 -1
  62. package/dist/js/jquery_wrapper.js +55 -55
  63. package/dist/js/tabulator.js +26054 -25713
  64. package/dist/js/tabulator.js.map +1 -1
  65. package/dist/js/tabulator.min.js +2 -2
  66. package/dist/js/tabulator.min.js.map +1 -1
  67. package/dist/js/tabulator_esm.js +26131 -25790
  68. package/dist/js/tabulator_esm.js.map +1 -1
  69. package/dist/js/tabulator_esm.min.js +2 -2
  70. package/dist/js/tabulator_esm.min.js.map +1 -1
  71. package/package.json +65 -65
  72. package/src/js/builds/esm.js +14 -14
  73. package/src/js/builds/jquery_wrapper.js +55 -55
  74. package/src/js/core/ColumnManager.js +745 -730
  75. package/src/js/core/CoreFeature.js +138 -138
  76. package/src/js/core/FooterManager.js +101 -101
  77. package/src/js/core/Module.js +141 -141
  78. package/src/js/core/RowManager.js +1128 -1101
  79. package/src/js/core/Tabulator.js +895 -892
  80. package/src/js/core/TabulatorFull.js +10 -10
  81. package/src/js/core/cell/Cell.js +295 -295
  82. package/src/js/core/cell/CellComponent.js +78 -76
  83. package/src/js/core/column/Column.js +949 -949
  84. package/src/js/core/column/ColumnComponent.js +152 -152
  85. package/src/js/core/column/defaults/options.js +17 -17
  86. package/src/js/core/defaults/options.js +65 -65
  87. package/src/js/core/modules/core.js +2 -2
  88. package/src/js/core/modules/optional.js +34 -34
  89. package/src/js/core/rendering/Renderer.js +203 -203
  90. package/src/js/core/rendering/renderers/BasicHorizontal.js +24 -19
  91. package/src/js/core/rendering/renderers/BasicVertical.js +83 -79
  92. package/src/js/core/rendering/renderers/VirtualDomHorizontal.js +582 -577
  93. package/src/js/core/rendering/renderers/VirtualDomVertical.js +634 -580
  94. package/src/js/core/row/PseudoRow.js +44 -44
  95. package/src/js/core/row/Row.js +457 -457
  96. package/src/js/core/row/RowComponent.js +93 -93
  97. package/src/js/core/tools/Alert.js +61 -61
  98. package/src/js/core/tools/ComponentFunctionBinder.js +32 -32
  99. package/src/js/core/tools/DataLoader.js +119 -119
  100. package/src/js/core/tools/DeprecationAdvisor.js +46 -46
  101. package/src/js/core/tools/ExternalEventBus.js +104 -104
  102. package/src/js/core/tools/Helpers.js +46 -46
  103. package/src/js/core/tools/InteractionMonitor.js +321 -321
  104. package/src/js/core/tools/InternalEventBus.js +161 -161
  105. package/src/js/core/tools/ModuleBinder.js +104 -104
  106. package/src/js/core/tools/OptionsList.js +44 -40
  107. package/src/js/core/tools/Popup.js +304 -304
  108. package/src/js/core/tools/TableRegistry.js +61 -61
  109. package/src/js/modules/Accessor/Accessor.js +115 -115
  110. package/src/js/modules/Ajax/Ajax.js +143 -143
  111. package/src/js/modules/Ajax/defaults/config.js +2 -2
  112. package/src/js/modules/Ajax/defaults/contentTypeFormatters.js +44 -44
  113. package/src/js/modules/Ajax/defaults/loaderPromise.js +86 -86
  114. package/src/js/modules/Ajax/defaults/urlGenerator.js +43 -43
  115. package/src/js/modules/Clipboard/Clipboard.js +279 -279
  116. package/src/js/modules/Clipboard/defaults/pasteActions.js +10 -10
  117. package/src/js/modules/Clipboard/defaults/pasteParsers.js +74 -74
  118. package/src/js/modules/ColumnCalcs/CalcComponent.js +47 -47
  119. package/src/js/modules/ColumnCalcs/ColumnCalcs.js +581 -568
  120. package/src/js/modules/ColumnCalcs/defaults/calculations.js +92 -85
  121. package/src/js/modules/Comms/Comms.js +51 -51
  122. package/src/js/modules/DataTree/DataTree.js +603 -603
  123. package/src/js/modules/Download/Download.js +148 -148
  124. package/src/js/modules/Download/defaults/downloaders/csv.js +61 -61
  125. package/src/js/modules/Download/defaults/downloaders/html.js +4 -4
  126. package/src/js/modules/Download/defaults/downloaders/json.js +33 -33
  127. package/src/js/modules/Download/defaults/downloaders/jsonLines.js +31 -31
  128. package/src/js/modules/Download/defaults/downloaders/pdf.js +111 -111
  129. package/src/js/modules/Download/defaults/downloaders/xlsx.js +102 -99
  130. package/src/js/modules/Download/defaults/downloaders.js +14 -14
  131. package/src/js/modules/Edit/Edit.js +734 -736
  132. package/src/js/modules/Edit/List.js +1048 -1033
  133. package/src/js/modules/Edit/defaults/editors/autocomplete.js +11 -11
  134. package/src/js/modules/Edit/defaults/editors/date.js +138 -110
  135. package/src/js/modules/Edit/defaults/editors/datetime.js +125 -97
  136. package/src/js/modules/Edit/defaults/editors/input.js +76 -74
  137. package/src/js/modules/Edit/defaults/editors/list.js +6 -6
  138. package/src/js/modules/Edit/defaults/editors/number.js +109 -107
  139. package/src/js/modules/Edit/defaults/editors/progress.js +126 -126
  140. package/src/js/modules/Edit/defaults/editors/range.js +80 -78
  141. package/src/js/modules/Edit/defaults/editors/select.js +9 -9
  142. package/src/js/modules/Edit/defaults/editors/star.js +145 -145
  143. package/src/js/modules/Edit/defaults/editors/textarea.js +122 -120
  144. package/src/js/modules/Edit/defaults/editors/tickCross.js +94 -96
  145. package/src/js/modules/Edit/defaults/editors/time.js +126 -98
  146. package/src/js/modules/Edit/defaults/editors.js +28 -28
  147. package/src/js/modules/Edit/inputMask.js +73 -73
  148. package/src/js/modules/Export/Export.js +626 -623
  149. package/src/js/modules/Export/ExportColumn.js +10 -10
  150. package/src/js/modules/Export/ExportRow.js +9 -9
  151. package/src/js/modules/Filter/Filter.js +903 -892
  152. package/src/js/modules/Filter/defaults/filters.js +107 -107
  153. package/src/js/modules/Format/Format.js +215 -212
  154. package/src/js/modules/Format/defaults/formatters/buttonCross.js +2 -2
  155. package/src/js/modules/Format/defaults/formatters/buttonTick.js +2 -2
  156. package/src/js/modules/Format/defaults/formatters/color.js +3 -3
  157. package/src/js/modules/Format/defaults/formatters/datetime.js +36 -36
  158. package/src/js/modules/Format/defaults/formatters/datetimediff.js +40 -40
  159. package/src/js/modules/Format/defaults/formatters/handle.js +3 -3
  160. package/src/js/modules/Format/defaults/formatters/html.js +2 -2
  161. package/src/js/modules/Format/defaults/formatters/image.js +39 -39
  162. package/src/js/modules/Format/defaults/formatters/link.js +77 -77
  163. package/src/js/modules/Format/defaults/formatters/lookup.js +9 -9
  164. package/src/js/modules/Format/defaults/formatters/money.js +43 -36
  165. package/src/js/modules/Format/defaults/formatters/plaintext.js +2 -2
  166. package/src/js/modules/Format/defaults/formatters/progress.js +132 -132
  167. package/src/js/modules/Format/defaults/formatters/responsiveCollapse.js +43 -43
  168. package/src/js/modules/Format/defaults/formatters/rowSelection.js +59 -59
  169. package/src/js/modules/Format/defaults/formatters/rownum.js +9 -9
  170. package/src/js/modules/Format/defaults/formatters/star.js +37 -37
  171. package/src/js/modules/Format/defaults/formatters/textarea.js +3 -3
  172. package/src/js/modules/Format/defaults/formatters/tickCross.js +21 -21
  173. package/src/js/modules/Format/defaults/formatters/traffic.js +46 -46
  174. package/src/js/modules/Format/defaults/formatters.js +42 -42
  175. package/src/js/modules/FrozenColumns/FrozenColumns.js +299 -299
  176. package/src/js/modules/FrozenRows/FrozenRows.js +169 -159
  177. package/src/js/modules/GroupRows/Group.js +597 -598
  178. package/src/js/modules/GroupRows/GroupComponent.js +70 -66
  179. package/src/js/modules/GroupRows/GroupRows.js +639 -639
  180. package/src/js/modules/History/History.js +171 -171
  181. package/src/js/modules/History/defaults/redoers.js +24 -24
  182. package/src/js/modules/History/defaults/undoers.js +24 -24
  183. package/src/js/modules/HtmlTableImport/HtmlTableImport.js +181 -181
  184. package/src/js/modules/Import/Import.js +193 -193
  185. package/src/js/modules/Import/defaults/importers/array.js +4 -4
  186. package/src/js/modules/Import/defaults/importers/csv.js +62 -62
  187. package/src/js/modules/Import/defaults/importers/json.js +7 -7
  188. package/src/js/modules/Import/defaults/importers.js +8 -8
  189. package/src/js/modules/Interaction/Interaction.js +337 -325
  190. package/src/js/modules/Keybindings/Keybindings.js +172 -172
  191. package/src/js/modules/Keybindings/defaults/actions.js +118 -118
  192. package/src/js/modules/Keybindings/defaults/bindings.js +12 -12
  193. package/src/js/modules/Layout/Layout.js +49 -49
  194. package/src/js/modules/Layout/defaults/modes/fitColumns.js +171 -171
  195. package/src/js/modules/Layout/defaults/modes/fitData.js +9 -9
  196. package/src/js/modules/Layout/defaults/modes/fitDataGeneral.js +9 -9
  197. package/src/js/modules/Layout/defaults/modes/fitDataStretch.js +39 -39
  198. package/src/js/modules/Layout/defaults/modes.js +11 -11
  199. package/src/js/modules/Localize/Localize.js +185 -185
  200. package/src/js/modules/Localize/defaults/langs.js +36 -36
  201. package/src/js/modules/Menu/Menu.js +302 -302
  202. package/src/js/modules/MoveColumns/MoveColumns.js +299 -299
  203. package/src/js/modules/MoveRows/MoveRows.js +635 -635
  204. package/src/js/modules/Mutator/Mutator.js +161 -161
  205. package/src/js/modules/Page/Page.js +881 -881
  206. package/src/js/modules/Page/defaults/pageCounters/pages.js +32 -32
  207. package/src/js/modules/Page/defaults/pageCounters/rows.js +39 -39
  208. package/src/js/modules/Page/defaults/pageCounters.js +7 -7
  209. package/src/js/modules/Persistence/Persistence.js +472 -458
  210. package/src/js/modules/Persistence/defaults/readers.js +29 -29
  211. package/src/js/modules/Persistence/defaults/writers.js +12 -12
  212. package/src/js/modules/Popup/Popup.js +231 -231
  213. package/src/js/modules/Print/Print.js +137 -137
  214. package/src/js/modules/ReactiveData/ReactiveData.js +408 -408
  215. package/src/js/modules/ResizeColumns/ResizeColumns.js +309 -309
  216. package/src/js/modules/ResizeRows/ResizeRows.js +111 -111
  217. package/src/js/modules/ResizeTable/ResizeTable.js +159 -159
  218. package/src/js/modules/ResponsiveLayout/ResponsiveLayout.js +348 -345
  219. package/src/js/modules/SelectRow/SelectRow.js +474 -444
  220. package/src/js/modules/Sort/Sort.js +470 -470
  221. package/src/js/modules/Sort/defaults/sorters/alphanum.js +43 -43
  222. package/src/js/modules/Sort/defaults/sorters/array.js +53 -53
  223. package/src/js/modules/Sort/defaults/sorters/boolean.js +6 -6
  224. package/src/js/modules/Sort/defaults/sorters/date.js +9 -9
  225. package/src/js/modules/Sort/defaults/sorters/datetime.js +43 -43
  226. package/src/js/modules/Sort/defaults/sorters/exists.js +6 -6
  227. package/src/js/modules/Sort/defaults/sorters/number.js +39 -39
  228. package/src/js/modules/Sort/defaults/sorters/string.js +33 -33
  229. package/src/js/modules/Sort/defaults/sorters/time.js +9 -9
  230. package/src/js/modules/Sort/defaults/sorters.js +20 -20
  231. package/src/js/modules/Tooltip/Tooltip.js +130 -130
  232. package/src/js/modules/Validate/Validate.js +305 -305
  233. package/src/js/modules/Validate/defaults/validators.js +138 -138
  234. package/src/scss/tabulator.scss +1496 -1467
  235. package/src/scss/themes/bootstrap/functions4.scss +118 -118
  236. package/src/scss/themes/bootstrap/functions5.scss +302 -302
  237. package/src/scss/themes/bootstrap/tabulator_bootstrap3.scss +288 -284
  238. package/src/scss/themes/bootstrap/tabulator_bootstrap4.scss +552 -544
  239. package/src/scss/themes/bootstrap/tabulator_bootstrap5.scss +584 -574
  240. package/src/scss/themes/bootstrap/variables3.scss +870 -870
  241. package/src/scss/themes/bootstrap/variables4.scss +930 -930
  242. package/src/scss/themes/bootstrap/variables5.scss +1641 -1641
  243. package/src/scss/themes/bulma/tabulator_bulma.scss +258 -252
  244. package/src/scss/themes/bulma/variables.scss +197 -197
  245. package/src/scss/themes/materialize/tabulator_materialize.scss +269 -265
  246. package/src/scss/themes/materialize/variables.scss +70 -70
  247. package/src/scss/themes/semanticui/tabulator_semanticui.scss +586 -561
  248. package/src/scss/themes/semanticui/variables.scss +839 -839
  249. package/src/scss/themes/semanticui/variables_table.scss +247 -247
  250. package/src/scss/themes/tabulator_midnight.scss +162 -158
  251. package/src/scss/themes/tabulator_modern.scss +239 -231
  252. package/src/scss/themes/tabulator_simple.scss +102 -102
  253. package/src/scss/themes/tabulator_site.scss +193 -189
@@ -1,580 +1,634 @@
1
- import Renderer from '../Renderer.js';
2
- import Helpers from '../../tools/Helpers.js';
3
-
4
- export default class VirtualDomVertical extends Renderer{
5
- constructor(table){
6
- super(table);
7
-
8
- this.verticalFillMode = "fill";
9
-
10
- this.scrollTop = 0;
11
- this.scrollLeft = 0;
12
-
13
- this.vDomRowHeight = 20; //approximation of row heights for padding
14
-
15
- this.vDomTop = 0; //hold position for first rendered row in the virtual DOM
16
- this.vDomBottom = 0; //hold position for last rendered row in the virtual DOM
17
-
18
- this.vDomScrollPosTop = 0; //last scroll position of the vDom top;
19
- this.vDomScrollPosBottom = 0; //last scroll position of the vDom bottom;
20
-
21
- this.vDomTopPad = 0; //hold value of padding for top of virtual DOM
22
- this.vDomBottomPad = 0; //hold value of padding for bottom of virtual DOM
23
-
24
- this.vDomMaxRenderChain = 90; //the maximum number of dom elements that can be rendered in 1 go
25
-
26
- this.vDomWindowBuffer = 0; //window row buffer before removing elements, to smooth scrolling
27
-
28
- this.vDomWindowMinTotalRows = 20; //minimum number of rows to be generated in virtual dom (prevent buffering issues on tables with tall rows)
29
- this.vDomWindowMinMarginRows = 5; //minimum number of rows to be generated in virtual dom margin
30
-
31
- this.vDomTopNewRows = []; //rows to normalize after appending to optimize render speed
32
- this.vDomBottomNewRows = []; //rows to normalize after appending to optimize render speed
33
- }
34
-
35
- //////////////////////////////////////
36
- ///////// Public Functions ///////////
37
- //////////////////////////////////////
38
-
39
- clearRows(){
40
- var element = this.tableElement;
41
-
42
- // element.children.detach();
43
- while(element.firstChild) element.removeChild(element.firstChild);
44
-
45
- element.style.paddingTop = "";
46
- element.style.paddingBottom = "";
47
- // element.style.minWidth = "";
48
- element.style.minHeight = "";
49
- element.style.display = "";
50
- element.style.visibility = "";
51
-
52
- this.elementVertical.scrollTop = 0;
53
- this.elementVertical.scrollLeft = 0;
54
-
55
- this.scrollTop = 0;
56
- this.scrollLeft = 0;
57
-
58
- this.vDomTop = 0;
59
- this.vDomBottom = 0;
60
- this.vDomTopPad = 0;
61
- this.vDomBottomPad = 0;
62
- this.vDomScrollPosTop = 0;
63
- this.vDomScrollPosBottom = 0;
64
- }
65
-
66
- renderRows(){
67
- this._virtualRenderFill();
68
- }
69
-
70
- rerenderRows(callback){
71
- var scrollTop = this.elementVertical.scrollTop;
72
- var topRow = false;
73
- var topOffset = false;
74
-
75
- var left = this.table.rowManager.scrollLeft;
76
-
77
- var rows = this.rows();
78
-
79
- for(var i = this.vDomTop; i <= this.vDomBottom; i++){
80
-
81
- if(rows[i]){
82
- var diff = scrollTop - rows[i].getElement().offsetTop;
83
-
84
- if(topOffset === false || Math.abs(diff) < topOffset){
85
- topOffset = diff;
86
- topRow = i;
87
- }else{
88
- break;
89
- }
90
- }
91
- }
92
-
93
- rows.forEach((row) => {
94
- row.deinitializeHeight();
95
- });
96
-
97
- if(callback){
98
- callback();
99
- }
100
-
101
- if(this.rows().length){
102
- this._virtualRenderFill((topRow === false ? this.rows.length - 1 : topRow), true, topOffset || 0);
103
- }else{
104
- this.clear();
105
- this.table.rowManager._showPlaceholder();
106
- }
107
-
108
- this.scrollColumns(left);
109
- }
110
-
111
- scrollColumns(left){
112
- this.table.rowManager.scrollHorizontal(left);
113
- }
114
-
115
- scrollRows(top, dir){
116
- var topDiff = top - this.vDomScrollPosTop;
117
- var bottomDiff = top - this.vDomScrollPosBottom;
118
- var margin = this.vDomWindowBuffer * 2;
119
- var rows = this.rows();
120
-
121
- this.scrollTop = top;
122
-
123
- if(-topDiff > margin || bottomDiff > margin){
124
- //if big scroll redraw table;
125
- var left = this.table.rowManager.scrollLeft;
126
- this._virtualRenderFill(Math.floor((this.elementVertical.scrollTop / this.elementVertical.scrollHeight) * rows.length));
127
- this.scrollColumns(left);
128
- }else{
129
-
130
- if(dir){
131
- //scrolling up
132
- if(topDiff < 0){
133
- this._addTopRow(rows, -topDiff);
134
- }
135
-
136
- if(bottomDiff < 0){
137
- //hide bottom row if needed
138
- if(this.vDomScrollHeight - this.scrollTop > this.vDomWindowBuffer){
139
- this._removeBottomRow(rows, -bottomDiff);
140
- }else{
141
- this.vDomScrollPosBottom = this.scrollTop;
142
- }
143
- }
144
- }else{
145
-
146
- if(bottomDiff >= 0){
147
- this._addBottomRow(rows, bottomDiff);
148
- }
149
-
150
- //scrolling down
151
- if(topDiff >= 0){
152
- //hide top row if needed
153
- if(this.scrollTop > this.vDomWindowBuffer){
154
- this._removeTopRow(rows, topDiff);
155
- }else{
156
- this.vDomScrollPosTop = this.scrollTop;
157
- }
158
- }
159
- }
160
- }
161
- }
162
-
163
- resize(){
164
- this.vDomWindowBuffer = this.table.options.renderVerticalBuffer || this.elementVertical.clientHeight;
165
- }
166
-
167
- scrollToRowNearestTop(row){
168
- var rowIndex = this.rows().indexOf(row);
169
-
170
- return !(Math.abs(this.vDomTop - rowIndex) > Math.abs(this.vDomBottom - rowIndex));
171
- }
172
-
173
- scrollToRow(row){
174
- var index = this.rows().indexOf(row);
175
-
176
- if(index > -1){
177
- this._virtualRenderFill(index, true);
178
- }
179
- }
180
-
181
- visibleRows(includingBuffer){
182
- var topEdge = this.elementVertical.scrollTop,
183
- bottomEdge = this.elementVertical.clientHeight + topEdge,
184
- topFound = false,
185
- topRow = 0,
186
- bottomRow = 0,
187
- rows = this.rows();
188
-
189
- if(includingBuffer){
190
- topRow = this.vDomTop;
191
- bottomRow = this.vDomBottom;
192
- }else{
193
- for(var i = this.vDomTop; i <= this.vDomBottom; i++){
194
- if(rows[i]){
195
- if(!topFound){
196
- if((topEdge - rows[i].getElement().offsetTop) >= 0){
197
- topRow = i;
198
- }else{
199
- topFound = true;
200
-
201
- if(bottomEdge - rows[i].getElement().offsetTop >= 0){
202
- bottomRow = i;
203
- }else{
204
- break;
205
- }
206
- }
207
- }else{
208
- if(bottomEdge - rows[i].getElement().offsetTop >= 0){
209
- bottomRow = i;
210
- }else{
211
- break;
212
- }
213
- }
214
- }
215
- }
216
- }
217
-
218
- return rows.slice(topRow, bottomRow + 1);
219
- }
220
-
221
- //////////////////////////////////////
222
- //////// Internal Rendering //////////
223
- //////////////////////////////////////
224
-
225
- //full virtual render
226
- _virtualRenderFill(position, forceMove, offset){
227
- var element = this.tableElement,
228
- holder = this.elementVertical,
229
- topPad = 0,
230
- rowsHeight = 0,
231
- heightOccupied = 0,
232
- topPadHeight = 0,
233
- i = 0,
234
- rows = this.rows(),
235
- rowsCount = rows.length,
236
- containerHeight = this.elementVertical.clientHeight;
237
-
238
- position = position || 0;
239
-
240
- offset = offset || 0;
241
-
242
- if(!position){
243
- this.clear();
244
- }else{
245
- while(element.firstChild) element.removeChild(element.firstChild);
246
-
247
- //check if position is too close to bottom of table
248
- heightOccupied = (rowsCount - position + 1) * this.vDomRowHeight;
249
-
250
- if(heightOccupied < containerHeight){
251
- position -= Math.ceil((containerHeight - heightOccupied) / this.vDomRowHeight);
252
- if(position < 0){
253
- position = 0;
254
- }
255
- }
256
-
257
- //calculate initial pad
258
- topPad = Math.min(Math.max(Math.floor(this.vDomWindowBuffer / this.vDomRowHeight), this.vDomWindowMinMarginRows), position);
259
- position -= topPad;
260
- }
261
-
262
- if(rowsCount && Helpers.elVisible(this.elementVertical)){
263
- this.vDomTop = position;
264
-
265
- this.vDomBottom = position -1;
266
-
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);
273
-
274
- element.appendChild(row.getElement());
275
-
276
- row.initialize();
277
-
278
- if(!row.heightInitialized){
279
- row.normalizeHeight(true);
280
- }
281
-
282
- rowHeight = row.getHeight();
283
-
284
- if(i < topPad){
285
- topPadHeight += rowHeight;
286
- }else{
287
- rowsHeight += rowHeight;
288
- }
289
-
290
- if(rowHeight > this.vDomWindowBuffer){
291
- this.vDomWindowBuffer = rowHeight * 2;
292
- }
293
-
294
- this.vDomBottom ++;
295
- i++;
296
- }
297
-
298
- if(!position){
299
- this.vDomTopPad = 0;
300
- //adjust row height to match average of rendered elements
301
- this.vDomRowHeight = Math.floor((rowsHeight + topPadHeight) / i);
302
- this.vDomBottomPad = this.vDomRowHeight * (rowsCount - this.vDomBottom -1);
303
-
304
- this.vDomScrollHeight = topPadHeight + rowsHeight + this.vDomBottomPad - containerHeight;
305
- }else{
306
- this.vDomTopPad = !forceMove ? this.scrollTop - topPadHeight : (this.vDomRowHeight * this.vDomTop) + offset;
307
- this.vDomBottomPad = this.vDomBottom == rowsCount-1 ? 0 : Math.max(this.vDomScrollHeight - this.vDomTopPad - rowsHeight - topPadHeight, 0);
308
- }
309
-
310
- element.style.paddingTop = this.vDomTopPad + "px";
311
- element.style.paddingBottom = this.vDomBottomPad + "px";
312
-
313
- if(forceMove){
314
- this.scrollTop = this.vDomTopPad + (topPadHeight) + offset - (this.elementVertical.scrollWidth > this.elementVertical.clientWidth ? this.elementVertical.offsetHeight - containerHeight : 0);
315
- }
316
-
317
- this.scrollTop = Math.min(this.scrollTop, this.elementVertical.scrollHeight - containerHeight);
318
-
319
- //adjust for horizontal scrollbar if present (and not at top of table)
320
- if(this.elementVertical.scrollWidth > this.elementVertical.offsetWidth && forceMove){
321
- this.scrollTop += this.elementVertical.offsetHeight - containerHeight;
322
- }
323
-
324
- this.vDomScrollPosTop = this.scrollTop;
325
- this.vDomScrollPosBottom = this.scrollTop;
326
-
327
- holder.scrollTop = this.scrollTop;
328
-
329
- this.dispatch("render-virtual-fill");
330
- }
331
- }
332
-
333
- _addTopRow(rows, fillableSpace){
334
- var table = this.tableElement,
335
- addedRows = [],
336
- paddingAdjust = 0,
337
- index = this.vDomTop -1,
338
- i = 0,
339
- working = true;
340
-
341
- while(working){
342
- if(this.vDomTop){
343
- let row = rows[index],
344
- rowHeight, initialized;
345
-
346
- if(row && i < this.vDomMaxRenderChain){
347
- rowHeight = row.getHeight() || this.vDomRowHeight;
348
- initialized = row.initialized;
349
-
350
- if(fillableSpace >= rowHeight){
351
-
352
- this.styleRow(row, index);
353
- table.insertBefore(row.getElement(), table.firstChild);
354
-
355
- if(!row.initialized || !row.heightInitialized){
356
- addedRows.push(row);
357
- }
358
-
359
- row.initialize();
360
-
361
- if(!initialized){
362
- rowHeight = row.getElement().offsetHeight;
363
-
364
- if(rowHeight > this.vDomWindowBuffer){
365
- this.vDomWindowBuffer = rowHeight * 2;
366
- }
367
- }
368
-
369
- fillableSpace -= rowHeight;
370
- paddingAdjust += rowHeight;
371
-
372
- this.vDomTop--;
373
- index--;
374
- i++;
375
-
376
- }else{
377
- working = false;
378
- }
379
-
380
- }else{
381
- working = false;
382
- }
383
-
384
- }else{
385
- working = false;
386
- }
387
- }
388
-
389
- for (let row of addedRows){
390
- row.clearCellHeight();
391
- }
392
-
393
- this._quickNormalizeRowHeight(addedRows);
394
-
395
- if(paddingAdjust){
396
- this.vDomTopPad -= paddingAdjust;
397
-
398
- if(this.vDomTopPad < 0){
399
- this.vDomTopPad = index * this.vDomRowHeight;
400
- }
401
-
402
- if(index < 1){
403
- this.vDomTopPad = 0;
404
- }
405
-
406
- table.style.paddingTop = this.vDomTopPad + "px";
407
- this.vDomScrollPosTop -= paddingAdjust;
408
- }
409
- }
410
-
411
- _removeTopRow(rows, fillableSpace){
412
- var removableRows = [],
413
- paddingAdjust = 0,
414
- i = 0,
415
- working = true;
416
-
417
- while(working){
418
- let row = rows[this.vDomTop],
419
- rowHeight;
420
-
421
- if(row && i < this.vDomMaxRenderChain){
422
- rowHeight = row.getHeight() || this.vDomRowHeight;
423
-
424
- if(fillableSpace >= rowHeight){
425
- this.vDomTop++;
426
-
427
- fillableSpace -= rowHeight;
428
- paddingAdjust += rowHeight;
429
-
430
- removableRows.push(row);
431
- i++;
432
- }else{
433
- working = false;
434
- }
435
- }else{
436
- working = false;
437
- }
438
- }
439
-
440
- for (let row of removableRows){
441
- let rowEl = row.getElement();
442
-
443
- if(rowEl.parentNode){
444
- rowEl.parentNode.removeChild(rowEl);
445
- }
446
- }
447
-
448
- if(paddingAdjust){
449
- this.vDomTopPad += paddingAdjust;
450
- this.tableElement.style.paddingTop = this.vDomTopPad + "px";
451
- this.vDomScrollPosTop += this.vDomTop ? paddingAdjust : paddingAdjust + this.vDomWindowBuffer;
452
- }
453
- }
454
-
455
- _addBottomRow(rows, fillableSpace){
456
- var table = this.tableElement,
457
- addedRows = [],
458
- paddingAdjust = 0,
459
- index = this.vDomBottom + 1,
460
- i = 0,
461
- working = true;
462
-
463
- while(working){
464
- let row = rows[index],
465
- rowHeight, initialized;
466
-
467
- if(row && i < this.vDomMaxRenderChain){
468
- rowHeight = row.getHeight() || this.vDomRowHeight;
469
- initialized = row.initialized;
470
-
471
- if(fillableSpace >= rowHeight){
472
-
473
- this.styleRow(row, index);
474
- table.appendChild(row.getElement());
475
-
476
- if(!row.initialized || !row.heightInitialized){
477
- addedRows.push(row);
478
- }
479
-
480
- row.initialize();
481
-
482
- if(!initialized){
483
- rowHeight = row.getElement().offsetHeight;
484
-
485
- if(rowHeight > this.vDomWindowBuffer){
486
- this.vDomWindowBuffer = rowHeight * 2;
487
- }
488
- }
489
-
490
- fillableSpace -= rowHeight;
491
- paddingAdjust += rowHeight;
492
-
493
- this.vDomBottom++;
494
- index++;
495
- i++;
496
- }else{
497
- working = false;
498
- }
499
- }else{
500
- working = false;
501
- }
502
- }
503
-
504
- for (let row of addedRows){
505
- row.clearCellHeight();
506
- }
507
-
508
- this._quickNormalizeRowHeight(addedRows);
509
-
510
- if(paddingAdjust){
511
- this.vDomBottomPad -= paddingAdjust;
512
-
513
- if(this.vDomBottomPad < 0 || index == rows.length -1){
514
- this.vDomBottomPad = 0;
515
- }
516
-
517
- table.style.paddingBottom = this.vDomBottomPad + "px";
518
- this.vDomScrollPosBottom += paddingAdjust;
519
- }
520
- }
521
-
522
- _removeBottomRow(rows, fillableSpace){
523
- var removableRows = [],
524
- paddingAdjust = 0,
525
- i = 0,
526
- working = true;
527
-
528
- while(working){
529
- let row = rows[this.vDomBottom],
530
- rowHeight;
531
-
532
- if(row && i < this.vDomMaxRenderChain){
533
- rowHeight = row.getHeight() || this.vDomRowHeight;
534
-
535
- if(fillableSpace >= rowHeight){
536
- this.vDomBottom --;
537
-
538
- fillableSpace -= rowHeight;
539
- paddingAdjust += rowHeight;
540
-
541
- removableRows.push(row);
542
- i++;
543
- }else{
544
- working = false;
545
- }
546
- }else{
547
- working = false;
548
- }
549
- }
550
-
551
- for (let row of removableRows){
552
- let rowEl = row.getElement();
553
-
554
- if(rowEl.parentNode){
555
- rowEl.parentNode.removeChild(rowEl);
556
- }
557
- }
558
-
559
- if(paddingAdjust){
560
- this.vDomBottomPad += paddingAdjust;
561
-
562
- if(this.vDomBottomPad < 0){
563
- this.vDomBottomPad = 0;
564
- }
565
-
566
- this.tableElement.style.paddingBottom = this.vDomBottomPad + "px";
567
- this.vDomScrollPosBottom -= paddingAdjust;
568
- }
569
- }
570
-
571
- _quickNormalizeRowHeight(rows){
572
- for(let row of rows){
573
- row.calcHeight();
574
- }
575
-
576
- for(let row of rows){
577
- row.setCellHeight();
578
- }
579
- }
580
- }
1
+ import Renderer from '../Renderer.js';
2
+ import Helpers from '../../tools/Helpers.js';
3
+
4
+ export default class VirtualDomVertical extends Renderer{
5
+ constructor(table){
6
+ super(table);
7
+
8
+ this.verticalFillMode = "fill";
9
+
10
+ this.scrollTop = 0;
11
+ this.scrollLeft = 0;
12
+
13
+ this.vDomRowHeight = 20; //approximation of row heights for padding
14
+
15
+ this.vDomTop = 0; //hold position for first rendered row in the virtual DOM
16
+ this.vDomBottom = 0; //hold position for last rendered row in the virtual DOM
17
+
18
+ this.vDomScrollPosTop = 0; //last scroll position of the vDom top;
19
+ this.vDomScrollPosBottom = 0; //last scroll position of the vDom bottom;
20
+
21
+ this.vDomTopPad = 0; //hold value of padding for top of virtual DOM
22
+ this.vDomBottomPad = 0; //hold value of padding for bottom of virtual DOM
23
+
24
+ this.vDomMaxRenderChain = 90; //the maximum number of dom elements that can be rendered in 1 go
25
+
26
+ this.vDomWindowBuffer = 0; //window row buffer before removing elements, to smooth scrolling
27
+
28
+ this.vDomWindowMinTotalRows = 20; //minimum number of rows to be generated in virtual dom (prevent buffering issues on tables with tall rows)
29
+ this.vDomWindowMinMarginRows = 5; //minimum number of rows to be generated in virtual dom margin
30
+
31
+ this.vDomTopNewRows = []; //rows to normalize after appending to optimize render speed
32
+ this.vDomBottomNewRows = []; //rows to normalize after appending to optimize render speed
33
+ }
34
+
35
+ //////////////////////////////////////
36
+ ///////// Public Functions ///////////
37
+ //////////////////////////////////////
38
+
39
+ clearRows(){
40
+ var element = this.tableElement;
41
+
42
+ // element.children.detach();
43
+ while(element.firstChild) element.removeChild(element.firstChild);
44
+
45
+ element.style.paddingTop = "";
46
+ element.style.paddingBottom = "";
47
+ element.style.minHeight = "";
48
+ element.style.display = "";
49
+ element.style.visibility = "";
50
+
51
+ this.elementVertical.scrollTop = 0;
52
+ this.elementVertical.scrollLeft = 0;
53
+
54
+ this.scrollTop = 0;
55
+ this.scrollLeft = 0;
56
+
57
+ this.vDomTop = 0;
58
+ this.vDomBottom = 0;
59
+ this.vDomTopPad = 0;
60
+ this.vDomBottomPad = 0;
61
+ this.vDomScrollPosTop = 0;
62
+ this.vDomScrollPosBottom = 0;
63
+ }
64
+
65
+ renderRows(){
66
+ this._virtualRenderFill();
67
+ }
68
+
69
+ rerenderRows(callback){
70
+ var scrollTop = this.elementVertical.scrollTop;
71
+ var topRow = false;
72
+ var topOffset = false;
73
+
74
+ var left = this.table.rowManager.scrollLeft;
75
+
76
+ var rows = this.rows();
77
+
78
+ for(var i = this.vDomTop; i <= this.vDomBottom; i++){
79
+
80
+ if(rows[i]){
81
+ var diff = scrollTop - rows[i].getElement().offsetTop;
82
+
83
+ if(topOffset === false || Math.abs(diff) < topOffset){
84
+ topOffset = diff;
85
+ topRow = i;
86
+ }else{
87
+ break;
88
+ }
89
+ }
90
+ }
91
+
92
+ rows.forEach((row) => {
93
+ row.deinitializeHeight();
94
+ });
95
+
96
+ if(callback){
97
+ callback();
98
+ }
99
+
100
+ if(this.rows().length){
101
+ this._virtualRenderFill((topRow === false ? this.rows.length - 1 : topRow), true, topOffset || 0);
102
+ }else{
103
+ this.clear();
104
+ this.table.rowManager.tableEmpty();
105
+ }
106
+
107
+ this.scrollColumns(left);
108
+ }
109
+
110
+ scrollColumns(left){
111
+ this.table.rowManager.scrollHorizontal(left);
112
+ }
113
+
114
+ scrollRows(top, dir){
115
+ var topDiff = top - this.vDomScrollPosTop;
116
+ var bottomDiff = top - this.vDomScrollPosBottom;
117
+ var margin = this.vDomWindowBuffer * 2;
118
+ var rows = this.rows();
119
+
120
+ this.scrollTop = top;
121
+
122
+ if(-topDiff > margin || bottomDiff > margin){
123
+ //if big scroll redraw table;
124
+ var left = this.table.rowManager.scrollLeft;
125
+ this._virtualRenderFill(Math.floor((this.elementVertical.scrollTop / this.elementVertical.scrollHeight) * rows.length));
126
+ this.scrollColumns(left);
127
+ }else{
128
+
129
+ if(dir){
130
+ //scrolling up
131
+ if(topDiff < 0){
132
+ this._addTopRow(rows, -topDiff);
133
+ }
134
+
135
+ if(bottomDiff < 0){
136
+ //hide bottom row if needed
137
+ if(this.vDomScrollHeight - this.scrollTop > this.vDomWindowBuffer){
138
+ this._removeBottomRow(rows, -bottomDiff);
139
+ }else{
140
+ this.vDomScrollPosBottom = this.scrollTop;
141
+ }
142
+ }
143
+ }else{
144
+
145
+ if(bottomDiff >= 0){
146
+ this._addBottomRow(rows, bottomDiff);
147
+ }
148
+
149
+ //scrolling down
150
+ if(topDiff >= 0){
151
+ //hide top row if needed
152
+ if(this.scrollTop > this.vDomWindowBuffer){
153
+ this._removeTopRow(rows, topDiff);
154
+ }else{
155
+ this.vDomScrollPosTop = this.scrollTop;
156
+ }
157
+ }
158
+ }
159
+ }
160
+ }
161
+
162
+ resize(){
163
+ this.vDomWindowBuffer = this.table.options.renderVerticalBuffer || this.elementVertical.clientHeight;
164
+ }
165
+
166
+ scrollToRowNearestTop(row){
167
+ var rowIndex = this.rows().indexOf(row);
168
+
169
+ return !(Math.abs(this.vDomTop - rowIndex) > Math.abs(this.vDomBottom - rowIndex));
170
+ }
171
+
172
+ scrollToRow(row){
173
+ var index = this.rows().indexOf(row);
174
+
175
+ if(index > -1){
176
+ this._virtualRenderFill(index, true);
177
+ }
178
+ }
179
+
180
+ visibleRows(includingBuffer){
181
+ var topEdge = this.elementVertical.scrollTop,
182
+ bottomEdge = this.elementVertical.clientHeight + topEdge,
183
+ topFound = false,
184
+ topRow = 0,
185
+ bottomRow = 0,
186
+ rows = this.rows();
187
+
188
+ if(includingBuffer){
189
+ topRow = this.vDomTop;
190
+ bottomRow = this.vDomBottom;
191
+ }else{
192
+ for(var i = this.vDomTop; i <= this.vDomBottom; i++){
193
+ if(rows[i]){
194
+ if(!topFound){
195
+ if((topEdge - rows[i].getElement().offsetTop) >= 0){
196
+ topRow = i;
197
+ }else{
198
+ topFound = true;
199
+
200
+ if(bottomEdge - rows[i].getElement().offsetTop >= 0){
201
+ bottomRow = i;
202
+ }else{
203
+ break;
204
+ }
205
+ }
206
+ }else{
207
+ if(bottomEdge - rows[i].getElement().offsetTop >= 0){
208
+ bottomRow = i;
209
+ }else{
210
+ break;
211
+ }
212
+ }
213
+ }
214
+ }
215
+ }
216
+
217
+ return rows.slice(topRow, bottomRow + 1);
218
+ }
219
+
220
+ //////////////////////////////////////
221
+ //////// Internal Rendering //////////
222
+ //////////////////////////////////////
223
+
224
+ //full virtual render
225
+ _virtualRenderFill(position, forceMove, offset) {
226
+ var element = this.tableElement,
227
+ holder = this.elementVertical,
228
+ topPad = 0,
229
+ rowsHeight = 0,
230
+ rowHeight = 0,
231
+ heightOccupied = 0,
232
+ topPadHeight = 0,
233
+ i = 0,
234
+ rows = this.rows(),
235
+ rowsCount = rows.length,
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;
246
+
247
+ position = position || 0;
248
+
249
+ offset = offset || 0;
250
+
251
+ if(!position){
252
+ this.clear();
253
+ }else {
254
+ while(element.firstChild) element.removeChild(element.firstChild);
255
+
256
+ //check if position is too close to bottom of table
257
+ heightOccupied = (rowsCount - position + 1) * this.vDomRowHeight;
258
+
259
+ if(heightOccupied < containerHeight){
260
+ position -= Math.ceil((containerHeight - heightOccupied) / this.vDomRowHeight);
261
+ if(position < 0){
262
+ position = 0;
263
+ }
264
+ }
265
+
266
+ //calculate initial pad
267
+ topPad = Math.min(Math.max(Math.floor(this.vDomWindowBuffer / this.vDomRowHeight), this.vDomWindowMinMarginRows), position);
268
+ position -= topPad;
269
+ }
270
+
271
+ if(rowsCount && Helpers.elVisible(this.elementVertical)){
272
+ this.vDomTop = position;
273
+ this.vDomBottom = position -1;
274
+
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
+ }
284
+
285
+ while(((rowsToRender == rowsCount || rowsHeight <= containerHeight + this.vDomWindowBuffer) || totalRowsRendered < this.vDomWindowMinTotalRows) && this.vDomBottom < rowsCount -1) {
286
+ renderedRows = [];
287
+ rowFragment = document.createDocumentFragment();
288
+
289
+ i = 0;
290
+ while ((i < rowsToRender) && this.vDomBottom < rowsCount -1) {
291
+ index = this.vDomBottom + 1,
292
+ row = rows[index];
293
+
294
+ this.styleRow(row, index);
295
+
296
+ row.initialize();
297
+ if(!row.heightInitialized && !this.table.options.rowHeight){
298
+ row.clearCellHeight();
299
+ }
300
+
301
+ rowFragment.appendChild(row.getElement());
302
+ renderedRows.push(row);
303
+ this.vDomBottom ++;
304
+ i++;
305
+ }
306
+
307
+ if(!renderedRows.length){
308
+ break;
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
+ }
336
+
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
+ }
350
+ }
351
+
352
+ if(!position){
353
+ this.vDomTopPad = 0;
354
+ //adjust row height to match average of rendered elements
355
+ this.vDomRowHeight = Math.floor((rowsHeight + topPadHeight) / totalRowsRendered);
356
+ this.vDomBottomPad = this.vDomRowHeight * (rowsCount - this.vDomBottom -1);
357
+
358
+ this.vDomScrollHeight = topPadHeight + rowsHeight + this.vDomBottomPad - containerHeight;
359
+ }else {
360
+ this.vDomTopPad = !forceMove ? this.scrollTop - topPadHeight : (this.vDomRowHeight * this.vDomTop) + offset;
361
+ this.vDomBottomPad = this.vDomBottom == rowsCount-1 ? 0 : Math.max(this.vDomScrollHeight - this.vDomTopPad - rowsHeight - topPadHeight, 0);
362
+ }
363
+
364
+ element.style.paddingTop = this.vDomTopPad+"px";
365
+ element.style.paddingBottom = this.vDomBottomPad+"px";
366
+
367
+ if(forceMove){
368
+ this.scrollTop = this.vDomTopPad + (topPadHeight) + offset - (this.elementVertical.scrollWidth > this.elementVertical.clientWidth ? this.elementVertical.offsetHeight - containerHeight : 0);
369
+ }
370
+
371
+ this.scrollTop = Math.min(this.scrollTop, this.elementVertical.scrollHeight - containerHeight);
372
+
373
+ //adjust for horizontal scrollbar if present (and not at top of table)
374
+ if(this.elementVertical.scrollWidth > this.elementVertical.clientWidth && forceMove){
375
+ this.scrollTop += this.elementVertical.offsetHeight - containerHeight;
376
+ }
377
+
378
+ this.vDomScrollPosTop = this.scrollTop;
379
+ this.vDomScrollPosBottom = this.scrollTop;
380
+
381
+ holder.scrollTop = this.scrollTop;
382
+
383
+ this.dispatch("render-virtual-fill");
384
+ }
385
+ }
386
+
387
+ _addTopRow(rows, fillableSpace){
388
+ var table = this.tableElement,
389
+ addedRows = [],
390
+ paddingAdjust = 0,
391
+ index = this.vDomTop -1,
392
+ i = 0,
393
+ working = true;
394
+
395
+ while(working){
396
+ if(this.vDomTop){
397
+ let row = rows[index],
398
+ rowHeight, initialized;
399
+
400
+ if(row && i < this.vDomMaxRenderChain){
401
+ rowHeight = row.getHeight() || this.vDomRowHeight;
402
+ initialized = row.initialized;
403
+
404
+ if(fillableSpace >= rowHeight){
405
+
406
+ this.styleRow(row, index);
407
+ table.insertBefore(row.getElement(), table.firstChild);
408
+
409
+ if(!row.initialized || !row.heightInitialized){
410
+ addedRows.push(row);
411
+ }
412
+
413
+ row.initialize();
414
+
415
+ if(!initialized){
416
+ rowHeight = row.getElement().offsetHeight;
417
+
418
+ if(rowHeight > this.vDomWindowBuffer){
419
+ this.vDomWindowBuffer = rowHeight * 2;
420
+ }
421
+ }
422
+
423
+ fillableSpace -= rowHeight;
424
+ paddingAdjust += rowHeight;
425
+
426
+ this.vDomTop--;
427
+ index--;
428
+ i++;
429
+
430
+ }else{
431
+ working = false;
432
+ }
433
+
434
+ }else{
435
+ working = false;
436
+ }
437
+
438
+ }else{
439
+ working = false;
440
+ }
441
+ }
442
+
443
+ for (let row of addedRows){
444
+ row.clearCellHeight();
445
+ }
446
+
447
+ this._quickNormalizeRowHeight(addedRows);
448
+
449
+ if(paddingAdjust){
450
+ this.vDomTopPad -= paddingAdjust;
451
+
452
+ if(this.vDomTopPad < 0){
453
+ this.vDomTopPad = index * this.vDomRowHeight;
454
+ }
455
+
456
+ if(index < 1){
457
+ this.vDomTopPad = 0;
458
+ }
459
+
460
+ table.style.paddingTop = this.vDomTopPad + "px";
461
+ this.vDomScrollPosTop -= paddingAdjust;
462
+ }
463
+ }
464
+
465
+ _removeTopRow(rows, fillableSpace){
466
+ var removableRows = [],
467
+ paddingAdjust = 0,
468
+ i = 0,
469
+ working = true;
470
+
471
+ while(working){
472
+ let row = rows[this.vDomTop],
473
+ rowHeight;
474
+
475
+ if(row && i < this.vDomMaxRenderChain){
476
+ rowHeight = row.getHeight() || this.vDomRowHeight;
477
+
478
+ if(fillableSpace >= rowHeight){
479
+ this.vDomTop++;
480
+
481
+ fillableSpace -= rowHeight;
482
+ paddingAdjust += rowHeight;
483
+
484
+ removableRows.push(row);
485
+ i++;
486
+ }else{
487
+ working = false;
488
+ }
489
+ }else{
490
+ working = false;
491
+ }
492
+ }
493
+
494
+ for (let row of removableRows){
495
+ let rowEl = row.getElement();
496
+
497
+ if(rowEl.parentNode){
498
+ rowEl.parentNode.removeChild(rowEl);
499
+ }
500
+ }
501
+
502
+ if(paddingAdjust){
503
+ this.vDomTopPad += paddingAdjust;
504
+ this.tableElement.style.paddingTop = this.vDomTopPad + "px";
505
+ this.vDomScrollPosTop += this.vDomTop ? paddingAdjust : paddingAdjust + this.vDomWindowBuffer;
506
+ }
507
+ }
508
+
509
+ _addBottomRow(rows, fillableSpace){
510
+ var table = this.tableElement,
511
+ addedRows = [],
512
+ paddingAdjust = 0,
513
+ index = this.vDomBottom + 1,
514
+ i = 0,
515
+ working = true;
516
+
517
+ while(working){
518
+ let row = rows[index],
519
+ rowHeight, initialized;
520
+
521
+ if(row && i < this.vDomMaxRenderChain){
522
+ rowHeight = row.getHeight() || this.vDomRowHeight;
523
+ initialized = row.initialized;
524
+
525
+ if(fillableSpace >= rowHeight){
526
+
527
+ this.styleRow(row, index);
528
+ table.appendChild(row.getElement());
529
+
530
+ if(!row.initialized || !row.heightInitialized){
531
+ addedRows.push(row);
532
+ }
533
+
534
+ row.initialize();
535
+
536
+ if(!initialized){
537
+ rowHeight = row.getElement().offsetHeight;
538
+
539
+ if(rowHeight > this.vDomWindowBuffer){
540
+ this.vDomWindowBuffer = rowHeight * 2;
541
+ }
542
+ }
543
+
544
+ fillableSpace -= rowHeight;
545
+ paddingAdjust += rowHeight;
546
+
547
+ this.vDomBottom++;
548
+ index++;
549
+ i++;
550
+ }else{
551
+ working = false;
552
+ }
553
+ }else{
554
+ working = false;
555
+ }
556
+ }
557
+
558
+ for (let row of addedRows){
559
+ row.clearCellHeight();
560
+ }
561
+
562
+ this._quickNormalizeRowHeight(addedRows);
563
+
564
+ if(paddingAdjust){
565
+ this.vDomBottomPad -= paddingAdjust;
566
+
567
+ if(this.vDomBottomPad < 0 || index == rows.length -1){
568
+ this.vDomBottomPad = 0;
569
+ }
570
+
571
+ table.style.paddingBottom = this.vDomBottomPad + "px";
572
+ this.vDomScrollPosBottom += paddingAdjust;
573
+ }
574
+ }
575
+
576
+ _removeBottomRow(rows, fillableSpace){
577
+ var removableRows = [],
578
+ paddingAdjust = 0,
579
+ i = 0,
580
+ working = true;
581
+
582
+ while(working){
583
+ let row = rows[this.vDomBottom],
584
+ rowHeight;
585
+
586
+ if(row && i < this.vDomMaxRenderChain){
587
+ rowHeight = row.getHeight() || this.vDomRowHeight;
588
+
589
+ if(fillableSpace >= rowHeight){
590
+ this.vDomBottom --;
591
+
592
+ fillableSpace -= rowHeight;
593
+ paddingAdjust += rowHeight;
594
+
595
+ removableRows.push(row);
596
+ i++;
597
+ }else{
598
+ working = false;
599
+ }
600
+ }else{
601
+ working = false;
602
+ }
603
+ }
604
+
605
+ for (let row of removableRows){
606
+ let rowEl = row.getElement();
607
+
608
+ if(rowEl.parentNode){
609
+ rowEl.parentNode.removeChild(rowEl);
610
+ }
611
+ }
612
+
613
+ if(paddingAdjust){
614
+ this.vDomBottomPad += paddingAdjust;
615
+
616
+ if(this.vDomBottomPad < 0){
617
+ this.vDomBottomPad = 0;
618
+ }
619
+
620
+ this.tableElement.style.paddingBottom = this.vDomBottomPad + "px";
621
+ this.vDomScrollPosBottom -= paddingAdjust;
622
+ }
623
+ }
624
+
625
+ _quickNormalizeRowHeight(rows){
626
+ for(let row of rows){
627
+ row.calcHeight();
628
+ }
629
+
630
+ for(let row of rows){
631
+ row.setCellHeight();
632
+ }
633
+ }
634
+ }