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
@@ -1,4 +1,4 @@
1
- /* Tabulator v5.4.4 (c) Oliver Folkerd 2023 */
1
+ /* Tabulator v5.5.0 (c) Oliver Folkerd 2023 */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
4
4
  typeof define === 'function' && define.amd ? define(factory) :
@@ -310,8 +310,8 @@
310
310
  return this._column;
311
311
  }
312
312
 
313
- scrollTo(){
314
- return this._column.table.columnManager.scrollToColumn(this._column);
313
+ scrollTo(position, ifVisible){
314
+ return this._column.table.columnManager.scrollToColumn(this._column, position, ifVisible);
315
315
  }
316
316
 
317
317
  getTable(){
@@ -419,10 +419,12 @@
419
419
  return this._cell.row.getComponent();
420
420
  }
421
421
 
422
- getData(){
423
- return this._cell.row.getData();
422
+ getData(transform){
423
+ return this._cell.row.getData(transform);
424
+ }
425
+ getType(){
426
+ return "cell";
424
427
  }
425
-
426
428
  getField(){
427
429
  return this._cell.column.getField();
428
430
  }
@@ -1996,9 +1998,14 @@
1996
1998
  super(table);
1997
1999
  }
1998
2000
 
1999
- renderRowCells(row){
2001
+ renderRowCells(row) {
2002
+ const rowFrag = document.createDocumentFragment();
2003
+ row.cells.forEach((cell) => {
2004
+ rowFrag.appendChild(cell.getElement());
2005
+ });
2006
+ row.element.appendChild(rowFrag);
2007
+
2000
2008
  row.cells.forEach((cell) => {
2001
- row.element.appendChild(cell.getElement());
2002
2009
  cell.cellRendered();
2003
2010
  });
2004
2011
  }
@@ -2183,8 +2190,13 @@
2183
2190
  if(this.initialized){
2184
2191
  this.initializeRow(row);
2185
2192
  }else {
2193
+ const rowFrag = document.createDocumentFragment();
2194
+ row.cells.forEach((cell) => {
2195
+ rowFrag.appendChild(cell.getElement());
2196
+ });
2197
+ row.element.appendChild(rowFrag);
2198
+
2186
2199
  row.cells.forEach((cell) => {
2187
- row.element.appendChild(cell.getElement());
2188
2200
  cell.cellRendered();
2189
2201
  });
2190
2202
  }
@@ -2619,6 +2631,8 @@
2619
2631
 
2620
2632
  this.contentsElement.insertBefore(this.headersElement, this.contentsElement.firstChild);
2621
2633
  this.element.insertBefore(this.contentsElement, this.element.firstChild);
2634
+
2635
+ this.initializeScrollWheelWatcher();
2622
2636
 
2623
2637
  this.subscribe("scroll-horizontal", this.scrollHorizontal.bind(this));
2624
2638
  this.subscribe("scrollbar-vertical", this.padVerticalScrollbar.bind(this));
@@ -2710,6 +2724,19 @@
2710
2724
 
2711
2725
  this.renderer.scrollColumns(left);
2712
2726
  }
2727
+
2728
+ initializeScrollWheelWatcher(){
2729
+ this.contentsElement.addEventListener("wheel", (e) => {
2730
+ var left;
2731
+
2732
+ if(e.deltaX){
2733
+ left = this.contentsElement.scrollLeft + e.deltaX;
2734
+
2735
+ this.table.rowManager.scrollHorizontal(left);
2736
+ this.table.columnManager.scrollHorizontal(left);
2737
+ }
2738
+ });
2739
+ }
2713
2740
 
2714
2741
  ///////////// Column Setup Functions /////////////
2715
2742
  generateColumnsFromRowData(data){
@@ -3364,8 +3391,8 @@
3364
3391
  return this._row.delete();
3365
3392
  }
3366
3393
 
3367
- scrollTo(){
3368
- return this._row.table.rowManager.scrollToRow(this._row);
3394
+ scrollTo(position, ifVisible){
3395
+ return this._row.table.rowManager.scrollToRow(this._row, position, ifVisible);
3369
3396
  }
3370
3397
 
3371
3398
  move(to, after){
@@ -3885,19 +3912,22 @@
3885
3912
  element.style.visibility = "";
3886
3913
  }
3887
3914
 
3888
- renderRows(){
3915
+ renderRows() {
3889
3916
  var element = this.tableElement,
3890
- onlyGroupHeaders = true;
3917
+ onlyGroupHeaders = true,
3918
+ tableFrag = document.createDocumentFragment();
3891
3919
 
3892
3920
  this.rows().forEach((row, index) => {
3893
3921
  this.styleRow(row, index);
3894
- element.appendChild(row.getElement());
3895
3922
  row.initialize(true);
3896
3923
 
3897
- if(row.type !== "group"){
3924
+ if (row.type !== "group") {
3898
3925
  onlyGroupHeaders = false;
3899
3926
  }
3927
+
3928
+ tableFrag.appendChild(row.getElement());
3900
3929
  });
3930
+ element.appendChild(tableFrag);
3901
3931
 
3902
3932
  if(onlyGroupHeaders){
3903
3933
  element.style.minWidth = this.table.columnManager.getWidth() + "px";
@@ -3978,7 +4008,6 @@
3978
4008
 
3979
4009
  element.style.paddingTop = "";
3980
4010
  element.style.paddingBottom = "";
3981
- // element.style.minWidth = "";
3982
4011
  element.style.minHeight = "";
3983
4012
  element.style.display = "";
3984
4013
  element.style.visibility = "";
@@ -4157,17 +4186,27 @@
4157
4186
  //////////////////////////////////////
4158
4187
 
4159
4188
  //full virtual render
4160
- _virtualRenderFill(position, forceMove, offset){
4189
+ _virtualRenderFill(position, forceMove, offset) {
4161
4190
  var element = this.tableElement,
4162
4191
  holder = this.elementVertical,
4163
4192
  topPad = 0,
4164
4193
  rowsHeight = 0,
4194
+ rowHeight = 0,
4165
4195
  heightOccupied = 0,
4166
4196
  topPadHeight = 0,
4167
4197
  i = 0,
4168
4198
  rows = this.rows(),
4169
4199
  rowsCount = rows.length,
4170
- containerHeight = this.elementVertical.clientHeight;
4200
+ index = 0,
4201
+ row,
4202
+ rowFragment,
4203
+ renderedRows = [],
4204
+ totalRowsRendered = 0,
4205
+ rowsToRender = 0,
4206
+ fixedHeight = this.table.rowManager.fixedHeight,
4207
+ containerHeight = this.elementVertical.clientHeight,
4208
+ avgRowHeight = this.table.options.rowHeight,
4209
+ resized = true;
4171
4210
 
4172
4211
  position = position || 0;
4173
4212
 
@@ -4195,44 +4234,89 @@
4195
4234
 
4196
4235
  if(rowsCount && Helpers.elVisible(this.elementVertical)){
4197
4236
  this.vDomTop = position;
4198
-
4199
4237
  this.vDomBottom = position -1;
4200
4238
 
4201
- while ((rowsHeight <= containerHeight + this.vDomWindowBuffer || i < this.vDomWindowMinTotalRows) && this.vDomBottom < rowsCount -1){
4202
- var index = this.vDomBottom + 1,
4203
- row = rows[index],
4204
- rowHeight = 0;
4205
-
4206
- this.styleRow(row, index);
4239
+ if(fixedHeight || this.table.options.maxHeight) {
4240
+ if(avgRowHeight) {
4241
+ rowsToRender = (containerHeight / avgRowHeight) + (this.vDomWindowBuffer / avgRowHeight);
4242
+ }
4243
+ rowsToRender = Math.max(this.vDomWindowMinTotalRows, Math.ceil(rowsToRender));
4244
+ }
4245
+ else {
4246
+ rowsToRender = rowsCount;
4247
+ }
4207
4248
 
4208
- element.appendChild(row.getElement());
4249
+ while(((rowsToRender == rowsCount || rowsHeight <= containerHeight + this.vDomWindowBuffer) || totalRowsRendered < this.vDomWindowMinTotalRows) && this.vDomBottom < rowsCount -1) {
4250
+ renderedRows = [];
4251
+ rowFragment = document.createDocumentFragment();
4209
4252
 
4210
- row.initialize();
4253
+ i = 0;
4254
+ while ((i < rowsToRender) && this.vDomBottom < rowsCount -1) {
4255
+ index = this.vDomBottom + 1,
4256
+ row = rows[index];
4211
4257
 
4212
- if(!row.heightInitialized){
4213
- row.normalizeHeight(true);
4214
- }
4258
+ this.styleRow(row, index);
4215
4259
 
4216
- rowHeight = row.getHeight();
4260
+ row.initialize();
4261
+ if(!row.heightInitialized && !this.table.options.rowHeight){
4262
+ row.clearCellHeight();
4263
+ }
4217
4264
 
4218
- if(i < topPad){
4219
- topPadHeight += rowHeight;
4220
- }else {
4221
- rowsHeight += rowHeight;
4265
+ rowFragment.appendChild(row.getElement());
4266
+ renderedRows.push(row);
4267
+ this.vDomBottom ++;
4268
+ i++;
4222
4269
  }
4223
4270
 
4224
- if(rowHeight > this.vDomWindowBuffer){
4225
- this.vDomWindowBuffer = rowHeight * 2;
4271
+ if(!renderedRows.length){
4272
+ break;
4226
4273
  }
4274
+ element.appendChild(rowFragment);
4275
+
4276
+ // NOTE: The next 3 loops are separate on purpose
4277
+ // This is to batch up the dom writes and reads which drastically improves performance
4278
+ renderedRows.forEach((row) => {
4279
+ if(!row.heightInitialized) {
4280
+ row.calcHeight(true);
4281
+
4282
+ }
4283
+ });
4284
+
4285
+ renderedRows.forEach((row) => {
4286
+ if(!row.heightInitialized) {
4287
+ row.setCellHeight();
4288
+
4289
+ }
4290
+ });
4291
+
4292
+ renderedRows.forEach((row) => {
4293
+ rowHeight = row.getHeight();
4294
+
4295
+ if(totalRowsRendered < topPad){
4296
+ topPadHeight += rowHeight;
4297
+ }else {
4298
+ rowsHeight += rowHeight;
4299
+ }
4300
+
4301
+ if(rowHeight > this.vDomWindowBuffer){
4302
+ this.vDomWindowBuffer = rowHeight * 2;
4303
+ }
4304
+ totalRowsRendered++;
4305
+ });
4227
4306
 
4228
- this.vDomBottom ++;
4229
- i++;
4307
+ resized = this.table.rowManager.adjustTableSize();
4308
+ containerHeight = this.elementVertical.clientHeight;
4309
+ if(resized && (fixedHeight || this.table.options.maxHeight))
4310
+ {
4311
+ avgRowHeight = rowsHeight / totalRowsRendered;
4312
+ rowsToRender = Math.max(this.vDomWindowMinTotalRows, Math.ceil((containerHeight / avgRowHeight) + (this.vDomWindowBuffer / avgRowHeight)));
4313
+ }
4230
4314
  }
4231
4315
 
4232
4316
  if(!position){
4233
4317
  this.vDomTopPad = 0;
4234
4318
  //adjust row height to match average of rendered elements
4235
- this.vDomRowHeight = Math.floor((rowsHeight + topPadHeight) / i);
4319
+ this.vDomRowHeight = Math.floor((rowsHeight + topPadHeight) / totalRowsRendered);
4236
4320
  this.vDomBottomPad = this.vDomRowHeight * (rowsCount - this.vDomBottom -1);
4237
4321
 
4238
4322
  this.vDomScrollHeight = topPadHeight + rowsHeight + this.vDomBottomPad - containerHeight;
@@ -4240,9 +4324,9 @@
4240
4324
  this.vDomTopPad = !forceMove ? this.scrollTop - topPadHeight : (this.vDomRowHeight * this.vDomTop) + offset;
4241
4325
  this.vDomBottomPad = this.vDomBottom == rowsCount-1 ? 0 : Math.max(this.vDomScrollHeight - this.vDomTopPad - rowsHeight - topPadHeight, 0);
4242
4326
  }
4243
-
4244
- element.style.paddingTop = this.vDomTopPad + "px";
4245
- element.style.paddingBottom = this.vDomBottomPad + "px";
4327
+
4328
+ element.style.paddingTop = this.vDomTopPad+"px";
4329
+ element.style.paddingBottom = this.vDomBottomPad+"px";
4246
4330
 
4247
4331
  if(forceMove){
4248
4332
  this.scrollTop = this.vDomTopPad + (topPadHeight) + offset - (this.elementVertical.scrollWidth > this.elementVertical.clientWidth ? this.elementVertical.offsetHeight - containerHeight : 0);
@@ -4545,7 +4629,7 @@
4545
4629
 
4546
4630
  this.dataPipeline = []; //hold data pipeline tasks
4547
4631
  this.displayPipeline = []; //hold data display pipeline tasks
4548
-
4632
+
4549
4633
  this.scrollbarWidth = 0;
4550
4634
 
4551
4635
  this.renderer = null;
@@ -4574,12 +4658,18 @@
4574
4658
 
4575
4659
  initializePlaceholder(){
4576
4660
  var placeholder = this.table.options.placeholder;
4577
-
4661
+
4662
+ if(typeof placeholder === "function"){
4663
+ placeholder = placeholder.call(this.table);
4664
+ }
4665
+
4666
+ placeholder = this.chain("placeholder", [placeholder], placeholder, placeholder) || placeholder;
4667
+
4578
4668
  //configure placeholder element
4579
4669
  if(placeholder){
4580
4670
  let el = document.createElement("div");
4581
4671
  el.classList.add("tabulator-placeholder");
4582
-
4672
+
4583
4673
  if(typeof placeholder == "string"){
4584
4674
  let contents = document.createElement("div");
4585
4675
  contents.classList.add("tabulator-placeholder-contents");
@@ -4595,10 +4685,10 @@
4595
4685
  this.placeholderContents = placeholder;
4596
4686
  }else {
4597
4687
  console.warn("Invalid placeholder provided, must be string or HTML Element", placeholder);
4598
-
4688
+
4599
4689
  this.el = null;
4600
4690
  }
4601
-
4691
+
4602
4692
  this.placeholder = el;
4603
4693
  }
4604
4694
  }
@@ -4759,15 +4849,15 @@
4759
4849
  this.destroy();
4760
4850
 
4761
4851
  this.adjustTableSize();
4762
-
4852
+
4763
4853
  this.dispatch("rows-wiped");
4764
4854
  }
4765
-
4855
+
4766
4856
  destroy(){
4767
4857
  this.rows.forEach((row) => {
4768
4858
  row.wipe();
4769
4859
  });
4770
-
4860
+
4771
4861
  this.rows = [];
4772
4862
  this.activeRows = [];
4773
4863
  this.activeRowsPipeline = [];
@@ -4840,7 +4930,7 @@
4840
4930
  rows.push(row);
4841
4931
  this.dispatch("row-added", row, item, pos, index);
4842
4932
  });
4843
-
4933
+
4844
4934
  this.refreshActiveData(refreshDisplayOnly ? "displayPipeline" : false, false, true);
4845
4935
 
4846
4936
  this.regenerateRowPositions();
@@ -5228,28 +5318,28 @@
5228
5318
 
5229
5319
  for(let i = index; i < this.dataPipeline.length; i++){
5230
5320
  let result = this.dataPipeline[i].handler(this.activeRowsPipeline[i].slice(0));
5231
-
5321
+
5232
5322
  this.activeRowsPipeline[i + 1] = result || this.activeRowsPipeline[i].slice(0);
5233
5323
  }
5234
-
5324
+
5235
5325
  this.setActiveRows(this.activeRowsPipeline[this.dataPipeline.length]);
5236
-
5326
+
5237
5327
  case "display":
5238
5328
  index = 0;
5239
5329
  this.resetDisplayRows();
5240
-
5330
+
5241
5331
  case "displayPipeline":
5242
5332
  for(let i = index; i < this.displayPipeline.length; i++){
5243
5333
  let result = this.displayPipeline[i].handler((i ? this.getDisplayRows(i - 1) : this.activeRows).slice(0), renderInPosition);
5244
-
5334
+
5245
5335
  this.setDisplayRows(result || this.getDisplayRows(i - 1).slice(0), i);
5246
5336
  }
5247
5337
 
5248
5338
  case "end":
5249
- //case to handle scenario when trying to skip past end stage
5339
+ //case to handle scenario when trying to skip past end stage
5250
5340
  this.regenerateRowPositions();
5251
5341
  }
5252
-
5342
+
5253
5343
  if(this.getDisplayRows().length){
5254
5344
  this._clearPlaceholder();
5255
5345
  }
@@ -5285,7 +5375,7 @@
5285
5375
  //set display row pipeline data
5286
5376
  setDisplayRows(displayRows, index){
5287
5377
  this.displayRows[index] = displayRows;
5288
-
5378
+
5289
5379
  if(index == this.displayRows.length -1){
5290
5380
  this.displayRowsCount = this.displayRows[this.displayRows.length -1].length;
5291
5381
  }
@@ -5320,7 +5410,7 @@
5320
5410
  //return only actual rows (not group headers etc)
5321
5411
  getRows(type){
5322
5412
  var rows = [];
5323
-
5413
+
5324
5414
  switch(type){
5325
5415
  case "active":
5326
5416
  rows = this.activeRows;
@@ -5329,11 +5419,11 @@
5329
5419
  case "display":
5330
5420
  rows = this.table.rowManager.getDisplayRows();
5331
5421
  break;
5332
-
5422
+
5333
5423
  case "visible":
5334
5424
  rows = this.getVisibleRows(false, true);
5335
5425
  break;
5336
-
5426
+
5337
5427
  default:
5338
5428
  rows = this.chain("rows-retrieve", type, null, this.rows) || this.rows;
5339
5429
  }
@@ -5354,25 +5444,25 @@
5354
5444
  this.dispatchExternal("renderStarted");
5355
5445
 
5356
5446
  this.renderer.rerenderRows(callback);
5357
-
5447
+
5358
5448
  if(!this.fixedHeight){
5359
5449
  this.adjustTableSize();
5360
5450
  }
5361
-
5451
+
5362
5452
  this.scrollBarCheck();
5363
5453
 
5364
5454
  this.dispatchExternal("renderComplete");
5365
5455
  }
5366
5456
  }
5367
-
5457
+
5368
5458
  scrollBarCheck(){
5369
5459
  var scrollbarWidth = 0;
5370
-
5460
+
5371
5461
  //adjust for vertical scrollbar moving table when present
5372
5462
  if(this.element.scrollHeight > this.element.clientHeight){
5373
5463
  scrollbarWidth = this.element.offsetWidth - this.element.clientWidth;
5374
5464
  }
5375
-
5465
+
5376
5466
  if(scrollbarWidth !== this.scrollbarWidth){
5377
5467
  this.scrollbarWidth = scrollbarWidth;
5378
5468
  this.dispatch("scrollbar-vertical", scrollbarWidth);
@@ -5425,7 +5515,7 @@
5425
5515
 
5426
5516
  if(this.firstRender){
5427
5517
  this.firstRender = false;
5428
-
5518
+
5429
5519
  if(!this.fixedHeight){
5430
5520
  this.adjustTableSize();
5431
5521
  }
@@ -5445,7 +5535,7 @@
5445
5535
  if(!this.displayRowsCount){
5446
5536
  this._showPlaceholder();
5447
5537
  }
5448
-
5538
+
5449
5539
  this.scrollBarCheck();
5450
5540
 
5451
5541
  this.dispatchExternal("renderComplete");
@@ -5470,7 +5560,7 @@
5470
5560
 
5471
5561
  this.renderer.clearRows();
5472
5562
  }
5473
-
5563
+
5474
5564
  tableEmpty(){
5475
5565
  this.renderEmptyScroll();
5476
5566
  this._showPlaceholder();
@@ -5478,6 +5568,12 @@
5478
5568
 
5479
5569
  _showPlaceholder(){
5480
5570
  if(this.placeholder){
5571
+ if(this.placeholder && this.placeholder.parentNode){
5572
+ this.placeholder.parentNode.removeChild(this.placeholder);
5573
+ }
5574
+
5575
+ this.initializePlaceholder();
5576
+
5481
5577
  this.placeholder.setAttribute("tabulator-render-mode", this.renderMode);
5482
5578
 
5483
5579
  this.getElement().appendChild(this.placeholder);
@@ -5489,7 +5585,7 @@
5489
5585
  if(this.placeholder && this.placeholder.parentNode){
5490
5586
  this.placeholder.parentNode.removeChild(this.placeholder);
5491
5587
  }
5492
-
5588
+
5493
5589
  // clear empty table placeholder min
5494
5590
  this.tableElement.style.minWidth = "";
5495
5591
  this.tableElement.style.display = "";
@@ -5524,7 +5620,8 @@
5524
5620
 
5525
5621
  //adjust the height of the table holder to fit in the Tabulator element
5526
5622
  adjustTableSize(){
5527
- var initialHeight = this.element.clientHeight, minHeight;
5623
+ let initialHeight = this.element.clientHeight, minHeight;
5624
+ let resized = false;
5528
5625
 
5529
5626
  if(this.renderer.verticalFillMode === "fill"){
5530
5627
  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));
@@ -5532,12 +5629,14 @@
5532
5629
  if(this.fixedHeight){
5533
5630
  minHeight = isNaN(this.table.options.minHeight) ? this.table.options.minHeight : this.table.options.minHeight + "px";
5534
5631
 
5632
+ const height = "calc(100% - " + otherHeight + "px)";
5535
5633
  this.element.style.minHeight = minHeight || "calc(100% - " + otherHeight + "px)";
5536
- this.element.style.height = "calc(100% - " + otherHeight + "px)";
5537
- this.element.style.maxHeight = "calc(100% - " + otherHeight + "px)";
5538
- }else {
5634
+ this.element.style.height = height;
5635
+ this.element.style.maxHeight = height;
5636
+ } else {
5539
5637
  this.element.style.height = "";
5540
- this.element.style.height = (this.table.element.clientHeight - otherHeight) + "px";
5638
+ this.element.style.height =
5639
+ this.table.element.clientHeight - otherHeight + "px";
5541
5640
  this.element.scrollTop = this.scrollTop;
5542
5641
  }
5543
5642
 
@@ -5545,17 +5644,19 @@
5545
5644
 
5546
5645
  //check if the table has changed size when dealing with variable height tables
5547
5646
  if(!this.fixedHeight && initialHeight != this.element.clientHeight){
5647
+ resized = true;
5548
5648
  if(this.subscribed("table-resize")){
5549
5649
  this.dispatch("table-resize");
5550
5650
  }else {
5551
5651
  this.redraw();
5552
5652
  }
5553
5653
  }
5554
-
5654
+
5555
5655
  this.scrollBarCheck();
5556
5656
  }
5557
5657
 
5558
5658
  this._positionPlaceholder();
5659
+ return resized;
5559
5660
  }
5560
5661
 
5561
5662
  //reinitialize all rows
@@ -5590,15 +5691,14 @@
5590
5691
 
5591
5692
  //redraw table
5592
5693
  redraw (force){
5593
- var left = this.scrollLeft;
5594
-
5595
- this.adjustTableSize();
5596
-
5694
+ const resized = this.adjustTableSize();
5597
5695
  this.table.tableWidth = this.table.element.clientWidth;
5598
5696
 
5599
5697
  if(!force){
5600
- this.reRenderInPosition();
5601
- this.scrollHorizontal(left);
5698
+ if(resized) {
5699
+ this.reRenderInPosition();
5700
+ }
5701
+ this.scrollHorizontal(this.scrollLeft);
5602
5702
  }else {
5603
5703
  this.renderTable();
5604
5704
  }
@@ -9525,6 +9625,13 @@
9525
9625
 
9526
9626
  return output;
9527
9627
  },
9628
+ "unique":function(values, data, calcParams){
9629
+ var unique = values.filter((value, index) => {
9630
+ return (values || value === 0) && values.indexOf(value) === index;
9631
+ });
9632
+
9633
+ return unique.length;
9634
+ },
9528
9635
  };
9529
9636
 
9530
9637
  class ColumnCalcs extends Module{
@@ -10399,7 +10506,7 @@
10399
10506
 
10400
10507
  row.create();
10401
10508
 
10402
- config = row.modules.dataTree.children;
10509
+ config = row.modules.dataTree;
10403
10510
 
10404
10511
  if(!config.index && config.children !== false){
10405
10512
  children = this.getChildren(row);
@@ -10910,8 +11017,11 @@
10910
11017
  workbook = XLSX.utils.book_new(),
10911
11018
  tableFeatures = new CoreFeature(this),
10912
11019
  compression = 'compress' in options ? options.compress : true,
11020
+ writeOptions = options.writeOptions || {bookType:'xlsx', bookSST:true, compression},
10913
11021
  output;
10914
11022
 
11023
+ writeOptions.type = 'binary';
11024
+
10915
11025
  workbook.SheetNames = [];
10916
11026
  workbook.Sheets = {};
10917
11027
 
@@ -10997,7 +11107,7 @@
10997
11107
  return buf;
10998
11108
  }
10999
11109
 
11000
- output = XLSX.write(workbook, {bookType:'xlsx', bookSST:true, type: 'binary', compression });
11110
+ output = XLSX.write(workbook, writeOptions);
11001
11111
 
11002
11112
  setFileContents(s2ab(output), "application/octet-stream");
11003
11113
  }
@@ -11295,7 +11405,7 @@
11295
11405
  input.value = typeof cellValue !== "undefined" ? cellValue : "";
11296
11406
 
11297
11407
  onRendered(function(){
11298
- if(cell._getSelf){
11408
+ if(cell.getType() === "cell"){
11299
11409
  input.focus({preventScroll: true});
11300
11410
  input.style.height = "100%";
11301
11411
 
@@ -11376,7 +11486,7 @@
11376
11486
  input.value = value;
11377
11487
 
11378
11488
  onRendered(function(){
11379
- if(cell._getSelf){
11489
+ if(cell.getType() === "cell"){
11380
11490
  input.focus({preventScroll: true});
11381
11491
  input.style.height = "100%";
11382
11492
 
@@ -11510,7 +11620,7 @@
11510
11620
  };
11511
11621
 
11512
11622
  onRendered(function () {
11513
- if(cell._getSelf){
11623
+ if(cell.getType() === "cell"){
11514
11624
  //submit new value on blur
11515
11625
  input.removeEventListener("blur", blurFunc);
11516
11626
 
@@ -11614,7 +11724,7 @@
11614
11724
  input.value = cellValue;
11615
11725
 
11616
11726
  onRendered(function () {
11617
- if(cell._getSelf){
11727
+ if(cell.getType() === "cell"){
11618
11728
  input.focus({preventScroll: true});
11619
11729
  input.style.height = "100%";
11620
11730
  }
@@ -11719,7 +11829,7 @@
11719
11829
  input.value = cellValue;
11720
11830
 
11721
11831
  onRendered(function(){
11722
- if(cell._getSelf){
11832
+ if(cell.getType() === "cell"){
11723
11833
  input.focus({preventScroll: true});
11724
11834
  input.style.height = "100%";
11725
11835
 
@@ -11846,7 +11956,7 @@
11846
11956
  input.value = cellValue;
11847
11957
 
11848
11958
  onRendered(function(){
11849
- if(cell._getSelf){
11959
+ if(cell.getType() == "cell"){
11850
11960
  input.focus({preventScroll: true});
11851
11961
  input.style.height = "100%";
11852
11962
 
@@ -11972,7 +12082,7 @@
11972
12082
  input.value = cellValue;
11973
12083
 
11974
12084
  onRendered(function(){
11975
- if(cell._getSelf){
12085
+ if(cell.getType() === "cell"){
11976
12086
  input.focus({preventScroll: true});
11977
12087
  input.style.height = "100%";
11978
12088
 
@@ -12067,7 +12177,7 @@
12067
12177
 
12068
12178
  this.initialValues = null;
12069
12179
 
12070
- this.isFilter = !cell._getSelf;
12180
+ this.isFilter = cell.getType() === "header";
12071
12181
 
12072
12182
  this.filterTimeout = null;
12073
12183
  this.filtered = false;
@@ -12133,7 +12243,7 @@
12133
12243
  function clickStop(e){
12134
12244
  e.stopPropagation();
12135
12245
  }
12136
-
12246
+
12137
12247
  if(!this.isFilter){
12138
12248
  this.input.style.height = "100%";
12139
12249
  this.input.focus({preventScroll: true});
@@ -12357,6 +12467,7 @@
12357
12467
  break;
12358
12468
 
12359
12469
  case 9: //tab
12470
+ this._keyTab(e);
12360
12471
  break;
12361
12472
 
12362
12473
  default:
@@ -12403,6 +12514,16 @@
12403
12514
  //////// Keyboard Navigation /////////
12404
12515
  //////////////////////////////////////
12405
12516
 
12517
+ _keyTab(e){
12518
+ if(this.params.autocomplete && this.lastAction === "typing"){
12519
+ this._resolveValue(true);
12520
+ }else {
12521
+ if(this.focusedItem){
12522
+ this._chooseItem(this.focusedItem, true);
12523
+ }
12524
+ }
12525
+ }
12526
+
12406
12527
  _keyUp(e){
12407
12528
  var index = this.displayItems.indexOf(this.focusedItem);
12408
12529
 
@@ -13040,7 +13161,7 @@
13040
13161
 
13041
13162
  _resolveValue(blur){
13042
13163
  var output, initialValue;
13043
-
13164
+
13044
13165
  if(this.popup){
13045
13166
  this.popup.hide(true);
13046
13167
  }
@@ -13420,7 +13541,7 @@
13420
13541
 
13421
13542
  if(this.table.browser != "firefox" && this.table.browser != "safari"){ //prevent blur issue on mac firefox
13422
13543
  onRendered(function(){
13423
- if(cell._getSelf){
13544
+ if(cell.getType() === "cell"){
13424
13545
  input.focus({preventScroll: true});
13425
13546
  }
13426
13547
  });
@@ -14009,8 +14130,8 @@
14009
14130
  cellEl = cell.getElement();
14010
14131
 
14011
14132
  if(this.table.modExists("frozenColumns")){
14012
- leftEdge += parseInt(this.table.modules.frozenColumns.leftMargin);
14013
- rightEdge -= parseInt(this.table.modules.frozenColumns.rightMargin);
14133
+ leftEdge += parseInt(this.table.modules.frozenColumns.leftMargin || 0);
14134
+ rightEdge -= parseInt(this.table.modules.frozenColumns.rightMargin || 0);
14014
14135
  }
14015
14136
 
14016
14137
  if(this.table.options.renderHorizontal === "virtual"){
@@ -14019,7 +14140,6 @@
14019
14140
  }
14020
14141
 
14021
14142
  if(cellEl.offsetLeft < leftEdge){
14022
-
14023
14143
  this.table.rowManager.element.scrollLeft -= (leftEdge - cellEl.offsetLeft);
14024
14144
  }else {
14025
14145
  if(cellEl.offsetLeft + cellEl.offsetWidth > rightEdge){
@@ -14727,6 +14847,9 @@
14727
14847
  getElement:function(){
14728
14848
  return cellEl;
14729
14849
  },
14850
+ getType:function(){
14851
+ return "cell";
14852
+ },
14730
14853
  getColumn:function(){
14731
14854
  return column.getComponent();
14732
14855
  },
@@ -14987,6 +15110,7 @@
14987
15110
  this.registerTableOption("initialFilter", false); //initial filtering criteria
14988
15111
  this.registerTableOption("initialHeaderFilter", false); //initial header filtering criteria
14989
15112
  this.registerTableOption("headerFilterLiveFilterDelay", 300); //delay before updating column after user types in header filter
15113
+ this.registerTableOption("placeholderHeaderFilter", false); //placeholder when header filter is empty
14990
15114
 
14991
15115
  this.registerColumnOption("headerFilter");
14992
15116
  this.registerColumnOption("headerFilterPlaceholder");
@@ -15022,6 +15146,7 @@
15022
15146
  this.subscribe("column-width-fit-before", this.hideHeaderFilterElements.bind(this));
15023
15147
  this.subscribe("column-width-fit-after", this.showHeaderFilterElements.bind(this));
15024
15148
  this.subscribe("table-built", this.tableBuilt.bind(this));
15149
+ this.subscribe("placeholder", this.generatePlaceholder.bind(this));
15025
15150
 
15026
15151
  if(this.table.options.filterMode === "remote"){
15027
15152
  this.subscribe("data-params", this.remoteFilterParams.bind(this));
@@ -15057,6 +15182,12 @@
15057
15182
  return params;
15058
15183
  }
15059
15184
 
15185
+ generatePlaceholder(text){
15186
+ if(this.table.options.placeholderHeaderFilter && Object.keys(this.headerFilters).length){
15187
+ return this.table.options.placeholderHeaderFilter;
15188
+ }
15189
+ }
15190
+
15060
15191
  ///////////////////////////////////
15061
15192
  ///////// Table Functions /////////
15062
15193
  ///////////////////////////////////
@@ -15340,6 +15471,9 @@
15340
15471
  getTable:() => {
15341
15472
  return this.table;
15342
15473
  },
15474
+ getType:() => {
15475
+ return "header";
15476
+ },
15343
15477
  getRow:function(){
15344
15478
  return {
15345
15479
  normalizeHeight:function(){
@@ -15871,7 +16005,7 @@
15871
16005
  function money(cell, formatterParams, onRendered){
15872
16006
  var floatVal = parseFloat(cell.getValue()),
15873
16007
  sign = "",
15874
- number, integer, decimal, rgx;
16008
+ number, integer, decimal, rgx, value;
15875
16009
 
15876
16010
  var decimalSym = formatterParams.decimal || ".";
15877
16011
  var thousandSym = formatterParams.thousand || ",";
@@ -15903,7 +16037,14 @@
15903
16037
  }
15904
16038
  }
15905
16039
 
15906
- return after ? sign + integer + decimal + symbol : sign + symbol + integer + decimal;
16040
+ value = integer + decimal;
16041
+
16042
+ if(sign === true){
16043
+ value = "(" + value + ")";
16044
+ return after ? value + symbol : symbol + value;
16045
+ }else {
16046
+ return after ? sign + value + symbol : sign + symbol + value;
16047
+ }
15907
16048
  }
15908
16049
 
15909
16050
  function link(cell, formatterParams, onRendered){
@@ -16609,6 +16750,9 @@
16609
16750
  getElement:function(){
16610
16751
  return el;
16611
16752
  },
16753
+ getType:function(){
16754
+ return "header";
16755
+ },
16612
16756
  getColumn:function(){
16613
16757
  return column.getComponent();
16614
16758
  },
@@ -16980,7 +17124,7 @@
16980
17124
  layoutElement(element, column){
16981
17125
  var position;
16982
17126
 
16983
- if(column.modules.frozen){
17127
+ if(column.modules.frozen && element){
16984
17128
  element.style.position = "sticky";
16985
17129
 
16986
17130
  if(this.table.rtl){
@@ -17244,6 +17388,10 @@
17244
17388
  this._group.toggleVisibility();
17245
17389
  }
17246
17390
 
17391
+ scrollTo(position, ifVisible){
17392
+ return this._group.groupManager.table.rowManager.scrollToRow(this._group, position, ifVisible);
17393
+ }
17394
+
17247
17395
  _getSelf(){
17248
17396
  return this._group;
17249
17397
  }
@@ -19277,8 +19425,20 @@
19277
19425
 
19278
19426
  this.subscribe("column-init", this.initializeColumn.bind(this));
19279
19427
  this.subscribe("cell-dblclick", this.cellContentsSelectionFixer.bind(this));
19428
+ this.subscribe("scroll-horizontal", this.clearTouchWatchers.bind(this));
19429
+ this.subscribe("scroll-vertical", this.clearTouchWatchers.bind(this));
19280
19430
  }
19281
19431
 
19432
+ clearTouchWatchers(){
19433
+ var types = Object.values(this.touchWatchers);
19434
+
19435
+ types.forEach((type) => {
19436
+ for(let key in type){
19437
+ type[key] = null;
19438
+ }
19439
+ });
19440
+ }
19441
+
19282
19442
  cellContentsSelectionFixer(e, cell){
19283
19443
  var range;
19284
19444
 
@@ -22234,6 +22394,7 @@
22234
22394
  this.config = {
22235
22395
  sort:this.table.options.persistence === true || this.table.options.persistence.sort,
22236
22396
  filter:this.table.options.persistence === true || this.table.options.persistence.filter,
22397
+ headerFilter:this.table.options.persistence === true || this.table.options.persistence.headerFilter,
22237
22398
  group:this.table.options.persistence === true || this.table.options.persistence.group,
22238
22399
  page:this.table.options.persistence === true || this.table.options.persistence.page,
22239
22400
  columns:this.table.options.persistence === true ? ["title", "width", "visible"] : this.table.options.persistence.columns,
@@ -22284,6 +22445,7 @@
22284
22445
  this.subscribe("table-redraw", this.tableRedraw.bind(this));
22285
22446
 
22286
22447
  this.subscribe("filter-changed", this.eventSave.bind(this, "filter"));
22448
+ this.subscribe("filter-changed", this.eventSave.bind(this, "headerFilter"));
22287
22449
  this.subscribe("sort-changed", this.eventSave.bind(this, "sort"));
22288
22450
  this.subscribe("group-changed", this.eventSave.bind(this, "group"));
22289
22451
  this.subscribe("page-changed", this.eventSave.bind(this, "page"));
@@ -22303,7 +22465,7 @@
22303
22465
  }
22304
22466
 
22305
22467
  tableBuilt(){
22306
- var sorters, filters;
22468
+ var sorters, filters, headerFilters;
22307
22469
 
22308
22470
  if(this.config.sort){
22309
22471
  sorters = this.load("sort");
@@ -22320,6 +22482,14 @@
22320
22482
  this.table.options.initialFilter = filters;
22321
22483
  }
22322
22484
  }
22485
+ if(this.config.headerFilter){
22486
+ headerFilters = this.load("headerFilter");
22487
+
22488
+ if(!headerFilters === false){
22489
+ this.table.options.initialHeaderFilter = headerFilters;
22490
+ }
22491
+ }
22492
+
22323
22493
  }
22324
22494
 
22325
22495
  tableRedraw(force){
@@ -22480,6 +22650,10 @@
22480
22650
  data = this.table.modules.filter.getFilters();
22481
22651
  break;
22482
22652
 
22653
+ case "headerFilter":
22654
+ data = this.table.modules.filter.getHeaderFilters();
22655
+ break;
22656
+
22483
22657
  case "sort":
22484
22658
  data = this.validateSorters(this.table.modules.sort.getSort());
22485
22659
  break;
@@ -24212,6 +24386,9 @@
24212
24386
  getData:function(){
24213
24387
  return data;
24214
24388
  },
24389
+ getType:function(){
24390
+ return "cell";
24391
+ },
24215
24392
  getElement:function(){
24216
24393
  return document.createElement("div");
24217
24394
  },
@@ -24476,7 +24653,7 @@
24476
24653
  }
24477
24654
 
24478
24655
  checkRowSelectability(row){
24479
- if(row.type === "row"){
24656
+ if(row && row.type === "row"){
24480
24657
  return this.table.options.selectableCheck.call(this.table, row.getComponent());
24481
24658
  }
24482
24659
 
@@ -24496,48 +24673,44 @@
24496
24673
 
24497
24674
  //select a number of rows
24498
24675
  selectRows(rows){
24499
- var rowMatch;
24676
+ var changes = [],
24677
+ rowMatch, change;
24500
24678
 
24501
24679
  switch(typeof rows){
24502
24680
  case "undefined":
24503
- this.table.rowManager.rows.forEach((row) => {
24504
- this._selectRow(row, true, true);
24505
- });
24506
-
24507
- this._rowSelectionChanged();
24681
+ rowMatch = this.table.rowManager.rows;
24508
24682
  break;
24509
24683
 
24510
24684
  case "string":
24511
24685
  rowMatch = this.table.rowManager.findRow(rows);
24512
24686
 
24513
- if(rowMatch){
24514
- this._selectRow(rowMatch, true, true);
24515
- this._rowSelectionChanged();
24516
- }else {
24687
+ if(!rowMatch){
24517
24688
  rowMatch = this.table.rowManager.getRows(rows);
24518
-
24519
- rowMatch.forEach((row) => {
24520
- this._selectRow(row, true, true);
24521
- });
24522
-
24523
- if(rowMatch.length){
24524
- this._rowSelectionChanged();
24525
- }
24526
24689
  }
24527
24690
  break;
24528
24691
 
24529
24692
  default:
24530
- if(Array.isArray(rows)){
24531
- rows.forEach((row) => {
24532
- this._selectRow(row, true, true);
24533
- });
24534
-
24535
- this._rowSelectionChanged();
24536
- }else {
24537
- this._selectRow(rows, false, true);
24538
- }
24693
+ rowMatch = rows;
24539
24694
  break;
24540
24695
  }
24696
+
24697
+ if(Array.isArray(rowMatch)){
24698
+ if(rowMatch.length){
24699
+ rowMatch.forEach((row) => {
24700
+ change = this._selectRow(row, true, true);
24701
+
24702
+ if(change){
24703
+ changes.push(change);
24704
+ }
24705
+ });
24706
+
24707
+ this._rowSelectionChanged(false, changes);
24708
+ }
24709
+ }else {
24710
+ if(rowMatch){
24711
+ this._selectRow(rowMatch, false, true);
24712
+ }
24713
+ }
24541
24714
  }
24542
24715
 
24543
24716
  //select an individual row
@@ -24575,7 +24748,9 @@
24575
24748
 
24576
24749
  this.dispatchExternal("rowSelected", row.getComponent());
24577
24750
 
24578
- this._rowSelectionChanged(silent);
24751
+ this._rowSelectionChanged(silent, row);
24752
+
24753
+ return row;
24579
24754
  }
24580
24755
  }else {
24581
24756
  if(!silent){
@@ -24590,39 +24765,51 @@
24590
24765
 
24591
24766
  //deselect a number of rows
24592
24767
  deselectRows(rows, silent){
24593
- var self = this,
24594
- rowCount;
24768
+ var changes = [],
24769
+ rowMatch, change;
24595
24770
 
24596
- if(typeof rows == "undefined"){
24771
+ switch(typeof rows){
24772
+ case "undefined":
24773
+ rowMatch = Object.assign([], this.selectedRows);
24774
+ break;
24597
24775
 
24598
- rowCount = self.selectedRows.length;
24776
+ case "string":
24777
+ rowMatch = this.table.rowManager.findRow(rows);
24599
24778
 
24600
- for(let i = 0; i < rowCount; i++){
24601
- self._deselectRow(self.selectedRows[0], true);
24602
- }
24779
+ if(!rowMatch){
24780
+ rowMatch = this.table.rowManager.getRows(rows);
24781
+ }
24782
+ break;
24603
24783
 
24604
- if(rowCount){
24605
- self._rowSelectionChanged(silent);
24784
+ default:
24785
+ rowMatch = rows;
24786
+ break;
24787
+ }
24788
+
24789
+ if(Array.isArray(rowMatch)){
24790
+ if(rowMatch.length){
24791
+ rowMatch.forEach((row) => {
24792
+ change = this._deselectRow(row, true, true);
24793
+
24794
+ if(change){
24795
+ changes.push(change);
24796
+ }
24797
+ });
24798
+
24799
+ this._rowSelectionChanged(silent, [], changes);
24606
24800
  }
24607
-
24608
24801
  }else {
24609
- if(Array.isArray(rows)){
24610
- rows.forEach(function(row){
24611
- self._deselectRow(row, true);
24612
- });
24613
-
24614
- self._rowSelectionChanged(silent);
24615
- }else {
24616
- self._deselectRow(rows, silent);
24802
+ if(rowMatch){
24803
+ this._deselectRow(rowMatch, silent, true);
24617
24804
  }
24618
- }
24805
+ }
24619
24806
  }
24620
24807
 
24621
24808
  //deselect an individual row
24622
24809
  _deselectRow(rowInfo, silent){
24623
24810
  var self = this,
24624
24811
  row = self.table.rowManager.findRow(rowInfo),
24625
- index;
24812
+ index, element;
24626
24813
 
24627
24814
  if(row){
24628
24815
  index = self.selectedRows.findIndex(function(selectedRow){
@@ -24630,8 +24817,13 @@
24630
24817
  });
24631
24818
 
24632
24819
  if(index > -1){
24820
+
24821
+ element = row.getElement();
24822
+
24823
+ if(element){
24824
+ element.classList.remove("tabulator-selected");
24825
+ }
24633
24826
 
24634
- row.getElement().classList.remove("tabulator-selected");
24635
24827
  if(!row.modules.select){
24636
24828
  row.modules.select = {};
24637
24829
  }
@@ -24648,7 +24840,9 @@
24648
24840
 
24649
24841
  this.dispatchExternal("rowDeselected", row.getComponent());
24650
24842
 
24651
- self._rowSelectionChanged(silent);
24843
+ self._rowSelectionChanged(silent, undefined, row);
24844
+
24845
+ return row;
24652
24846
  }
24653
24847
  }else {
24654
24848
  if(!silent){
@@ -24668,7 +24862,6 @@
24668
24862
  }
24669
24863
 
24670
24864
  getSelectedRows(){
24671
-
24672
24865
  var rows = [];
24673
24866
 
24674
24867
  this.selectedRows.forEach(function(row){
@@ -24678,7 +24871,7 @@
24678
24871
  return rows;
24679
24872
  }
24680
24873
 
24681
- _rowSelectionChanged(silent){
24874
+ _rowSelectionChanged(silent, selected = [], deselected = []){
24682
24875
  if(this.headerCheckboxElement){
24683
24876
  if(this.selectedRows.length === 0){
24684
24877
  this.headerCheckboxElement.checked = false;
@@ -24693,7 +24886,19 @@
24693
24886
  }
24694
24887
 
24695
24888
  if(!silent){
24696
- this.dispatchExternal("rowSelectionChanged", this.getSelectedData(), this.getSelectedRows());
24889
+ if(!Array.isArray(selected)){
24890
+ selected = [selected];
24891
+ }
24892
+
24893
+ selected = selected.map(row => row.getComponent());
24894
+
24895
+ if(!Array.isArray(deselected)){
24896
+ deselected = [deselected];
24897
+ }
24898
+
24899
+ deselected = deselected.map(row => row.getComponent());
24900
+
24901
+ this.dispatchExternal("rowSelectionChanged", this.getSelectedData(), this.getSelectedRows(), selected, deselected);
24697
24902
  }
24698
24903
  }
24699
24904