tabulator-tables 5.0.7 → 5.1.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 (116) hide show
  1. package/.editorconfig +6 -0
  2. package/LICENSE +1 -1
  3. package/bower.json +1 -1
  4. package/build/rollup.js +1 -1
  5. package/dist/css/tabulator.css +15 -2
  6. package/dist/css/tabulator.css.map +1 -1
  7. package/dist/css/tabulator.min.css +1 -1
  8. package/dist/css/tabulator.min.css.map +1 -1
  9. package/dist/css/tabulator_bootstrap3.css +15 -2
  10. package/dist/css/tabulator_bootstrap3.css.map +1 -1
  11. package/dist/css/tabulator_bootstrap3.min.css +1 -1
  12. package/dist/css/tabulator_bootstrap3.min.css.map +1 -1
  13. package/dist/css/tabulator_bootstrap4.css +15 -2
  14. package/dist/css/tabulator_bootstrap4.css.map +1 -1
  15. package/dist/css/tabulator_bootstrap4.min.css +1 -1
  16. package/dist/css/tabulator_bootstrap4.min.css.map +1 -1
  17. package/dist/css/tabulator_bulma.css +15 -2
  18. package/dist/css/tabulator_bulma.css.map +1 -1
  19. package/dist/css/tabulator_bulma.min.css +1 -1
  20. package/dist/css/tabulator_bulma.min.css.map +1 -1
  21. package/dist/css/tabulator_materialize.css +22 -6
  22. package/dist/css/tabulator_materialize.css.map +1 -1
  23. package/dist/css/tabulator_materialize.min.css +1 -1
  24. package/dist/css/tabulator_materialize.min.css.map +1 -1
  25. package/dist/css/tabulator_midnight.css +19 -2
  26. package/dist/css/tabulator_midnight.css.map +1 -1
  27. package/dist/css/tabulator_midnight.min.css +1 -1
  28. package/dist/css/tabulator_midnight.min.css.map +1 -1
  29. package/dist/css/tabulator_modern.css +15 -2
  30. package/dist/css/tabulator_modern.css.map +1 -1
  31. package/dist/css/tabulator_modern.min.css +1 -1
  32. package/dist/css/tabulator_modern.min.css.map +1 -1
  33. package/dist/css/tabulator_semanticui.css +15 -2
  34. package/dist/css/tabulator_semanticui.css.map +1 -1
  35. package/dist/css/tabulator_semanticui.min.css +1 -1
  36. package/dist/css/tabulator_semanticui.min.css.map +1 -1
  37. package/dist/css/tabulator_simple.css +15 -2
  38. package/dist/css/tabulator_simple.css.map +1 -1
  39. package/dist/css/tabulator_simple.min.css +1 -1
  40. package/dist/css/tabulator_simple.min.css.map +1 -1
  41. package/dist/css/tabulator_site.css +19 -2
  42. package/dist/css/tabulator_site.css.map +1 -1
  43. package/dist/css/tabulator_site.min.css +1 -1
  44. package/dist/css/tabulator_site.min.css.map +1 -1
  45. package/dist/js/tabulator.js +1121 -533
  46. package/dist/js/tabulator.js.map +1 -1
  47. package/dist/js/tabulator.min.js +2 -2
  48. package/dist/js/tabulator.min.js.map +1 -1
  49. package/dist/js/tabulator_esm.js +1566 -991
  50. package/dist/js/tabulator_esm.js.map +1 -1
  51. package/dist/js/tabulator_esm.min.js +2 -2
  52. package/dist/js/tabulator_esm.min.js.map +1 -1
  53. package/package.json +1 -1
  54. package/src/js/core/ColumnManager.js +4 -2
  55. package/src/js/core/CoreFeature.js +1 -5
  56. package/src/js/core/RowManager.js +15 -9
  57. package/src/js/core/Tabulator.js +14 -59
  58. package/src/js/core/cell/Cell.js +5 -1
  59. package/src/js/core/column/Column.js +21 -6
  60. package/src/js/core/column/ColumnComponent.js +4 -0
  61. package/src/js/core/column/defaults/options.js +1 -0
  62. package/src/js/core/defaults/options.js +3 -3
  63. package/src/js/core/modules/optional.js +1 -0
  64. package/src/js/core/rendering/Renderer.js +3 -2
  65. package/src/js/core/rendering/renderers/BasicVertical.js +2 -1
  66. package/src/js/core/rendering/renderers/VirtualDomHorizontal.js +165 -151
  67. package/src/js/core/rendering/renderers/VirtualDomVertical.js +1 -1
  68. package/src/js/core/row/Row.js +2 -2
  69. package/src/js/core/tools/{ComponentFuctionBinder.js → ComponentFunctionBinder.js} +1 -1
  70. package/src/js/core/tools/DataLoader.js +6 -6
  71. package/src/js/core/tools/InteractionMonitor.js +149 -49
  72. package/src/js/core/tools/OptionsList.js +2 -2
  73. package/src/js/modules/Ajax/Ajax.js +62 -82
  74. package/src/js/modules/ColumnCalcs/ColumnCalcs.js +15 -2
  75. package/src/js/modules/DataTree/DataTree.js +23 -9
  76. package/src/js/modules/Download/defaults/downloaders/json.js +1 -1
  77. package/src/js/modules/Download/defaults/downloaders/jsonLines.js +32 -0
  78. package/src/js/modules/Download/defaults/downloaders/pdf.js +0 -2
  79. package/src/js/modules/Download/defaults/downloaders/xlsx.js +3 -2
  80. package/src/js/modules/Download/defaults/downloaders.js +2 -0
  81. package/src/js/modules/Edit/Edit.js +27 -39
  82. package/src/js/modules/Edit/defaults/editors/progress.js +2 -2
  83. package/src/js/modules/Export/Export.js +1 -1
  84. package/src/js/modules/Filter/Filter.js +2 -2
  85. package/src/js/modules/Format/defaults/formatters/datetime.js +2 -2
  86. package/src/js/modules/Format/defaults/formatters/datetimediff.js +2 -1
  87. package/src/js/modules/FrozenColumns/FrozenColumns.js +1 -1
  88. package/src/js/modules/FrozenRows/FrozenRows.js +9 -0
  89. package/src/js/modules/GroupRows/Group.js +18 -67
  90. package/src/js/modules/GroupRows/GroupRows.js +8 -3
  91. package/src/js/modules/HtmlTableImport/HtmlTableImport.js +4 -7
  92. package/src/js/modules/Import/Import.js +197 -0
  93. package/src/js/modules/Import/defaults/importers/csv.js +63 -0
  94. package/src/js/modules/Import/defaults/importers/json.js +8 -0
  95. package/src/js/modules/Import/defaults/importers.js +7 -0
  96. package/src/js/modules/Interaction/Interaction.js +5 -0
  97. package/src/js/modules/Keybindings/Keybindings.js +9 -14
  98. package/src/js/modules/Keybindings/defaults/bindings.js +3 -3
  99. package/src/js/modules/Localize/defaults/langs.js +6 -0
  100. package/src/js/modules/Menu/Menu.js +200 -155
  101. package/src/js/modules/MoveColumns/MoveColumns.js +58 -57
  102. package/src/js/modules/MoveRows/MoveRows.js +4 -0
  103. package/src/js/modules/Page/Page.js +279 -183
  104. package/src/js/modules/Page/defaults/pageCounters/pages.js +33 -0
  105. package/src/js/modules/Page/defaults/pageCounters/rows.js +32 -0
  106. package/src/js/modules/Page/defaults/pageCounters.js +8 -0
  107. package/src/js/modules/ResizeRows/ResizeRows.js +1 -1
  108. package/src/js/modules/ResponsiveLayout/ResponsiveLayout.js +3 -5
  109. package/src/js/modules/SelectRow/SelectRow.js +4 -8
  110. package/src/js/modules/Sort/Sort.js +1 -1
  111. package/src/js/modules/Sort/defaults/sorters/datetime.js +3 -2
  112. package/src/js/modules/Validate/Validate.js +7 -5
  113. package/src/scss/tabulator.scss +20 -2
  114. package/src/scss/themes/materialize/tabulator_materialize.scss +5 -4
  115. package/src/scss/themes/tabulator_midnight.scss +4 -0
  116. package/src/scss/themes/tabulator_site.scss +4 -0
@@ -1,4 +1,4 @@
1
- /* Tabulator v5.0.7 (c) Oliver Folkerd 2021 */
1
+ /* Tabulator v5.1.0 (c) Oliver Folkerd 2022 */
2
2
  class CoreFeature{
3
3
 
4
4
  constructor(table){
@@ -103,11 +103,7 @@ class CoreFeature{
103
103
  //////////////// Options /////////////////
104
104
  //////////////////////////////////////////
105
105
 
106
- options(key, value){
107
- if(typeof value !== "undefined"){
108
- this.table.options[key] = value;
109
- }
110
-
106
+ options(key){
111
107
  return this.table.options[key];
112
108
  }
113
109
 
@@ -539,144 +535,125 @@ var defaultContentTypeFormatters = {
539
535
  };
540
536
 
541
537
  class Ajax extends Module{
542
-
538
+
543
539
  constructor(table){
544
540
  super(table);
545
-
546
- this.config = false; //hold config object for ajax request
541
+
542
+ this.config = {}; //hold config object for ajax request
547
543
  this.url = ""; //request URL
548
544
  this.urlGenerator = false;
549
545
  this.params = false; //request parameters
550
-
546
+
551
547
  this.loaderPromise = false;
552
-
548
+
553
549
  this.registerTableOption("ajaxURL", false); //url for ajax loading
554
550
  this.registerTableOption("ajaxURLGenerator", false);
555
551
  this.registerTableOption("ajaxParams", {}); //params for ajax loading
556
552
  this.registerTableOption("ajaxConfig", "get"); //ajax request type
557
553
  this.registerTableOption("ajaxContentType", "form"); //ajax request type
558
554
  this.registerTableOption("ajaxRequestFunc", false); //promise function
559
-
555
+
560
556
  this.registerTableOption("ajaxRequesting", function(){});
561
557
  this.registerTableOption("ajaxResponse", false);
562
-
558
+
563
559
  this.contentTypeFormatters = Ajax.contentTypeFormatters;
564
560
  }
565
-
561
+
566
562
  //initialize setup options
567
563
  initialize(){
568
564
  this.loaderPromise = this.table.options.ajaxRequestFunc || Ajax.defaultLoaderPromise;
569
565
  this.urlGenerator = this.table.options.ajaxURLGenerator || Ajax.defaultURLGenerator;
570
-
571
- if(this.table.options.ajaxParams){
572
- this.setParams(this.table.options.ajaxParams);
573
- }
574
-
575
- if(this.table.options.ajaxConfig){
576
- this.setConfig(this.table.options.ajaxConfig);
577
- }
578
-
566
+
579
567
  if(this.table.options.ajaxURL){
580
568
  this.setUrl(this.table.options.ajaxURL);
581
569
  }
582
570
 
583
- this.registerTableFunction("getAjaxUrl", this.getUrl.bind(this));
584
571
 
572
+ this.setDefaultConfig(this.table.options.ajaxConfig);
573
+
574
+ this.registerTableFunction("getAjaxUrl", this.getUrl.bind(this));
575
+
585
576
  this.subscribe("data-loading", this.requestDataCheck.bind(this));
577
+ this.subscribe("data-params", this.requestParams.bind(this));
586
578
  this.subscribe("data-load", this.requestData.bind(this));
587
579
  }
588
-
589
-
580
+
581
+ requestParams(data, config, silent, params){
582
+ var ajaxParams = this.table.options.ajaxParams;
583
+
584
+ if(ajaxParams){
585
+ if(typeof ajaxParams === "function"){
586
+ ajaxParams = ajaxParams.call(this.table);
587
+ }
588
+
589
+ params = Object.assign(params, ajaxParams);
590
+ }
591
+
592
+ return params;
593
+ }
594
+
590
595
  requestDataCheck(data, params, config, silent){
591
596
  return !!((!data && this.url) || typeof data === "string");
592
597
  }
593
-
594
- requestData(data, params, config, silent, previousData){
595
- if(this.requestDataCheck(data)){
596
- if(data){
597
- this.setUrl(data);
598
- }
599
-
600
- if(params){
601
- this.setParams(params, true);
602
- }
603
-
604
- if(config){
605
- this.setConfig(config);
606
- }
607
-
608
- return this.sendRequest();
598
+
599
+ requestData(url, params, config, silent, previousData){
600
+ var ajaxConfig;
601
+
602
+ if(!previousData && this.requestDataCheck(url)){
603
+ if(url){
604
+ this.setUrl(url);
605
+ }
606
+
607
+ ajaxConfig = this.generateConfig(config);
608
+
609
+ return this.sendRequest(this.url, params, ajaxConfig);
609
610
  }else {
610
611
  return previousData;
611
612
  }
612
613
  }
614
+
615
+ setDefaultConfig(config = {}){
616
+ this.config = Object.assign({}, Ajax.defaultConfig);
613
617
 
614
- //set ajax params
615
- setParams(params, update){
616
- if(update){
617
- this.params = this.params || {};
618
-
619
- for(let key in params){
620
- this.params[key] = params[key];
621
- }
618
+ if(typeof config == "string"){
619
+ this.config.method = config;
622
620
  }else {
623
- this.params = params;
621
+ Object.assign(this.config, config);
624
622
  }
625
623
  }
626
-
627
- getParams(){
628
- return this.params || {};
629
- }
630
-
624
+
631
625
  //load config object
632
- setConfig(config){
633
- this._loadDefaultConfig();
634
-
626
+ generateConfig(config = {}){
627
+ var ajaxConfig = Object.assign({}, this.config);
628
+
635
629
  if(typeof config == "string"){
636
- this.config.method = config;
630
+ ajaxConfig.method = config;
637
631
  }else {
638
- for(let key in config){
639
- this.config[key] = config[key];
640
- }
641
- }
642
- }
643
-
644
- //create config object from default
645
- _loadDefaultConfig(force){
646
- if(!this.config || force){
647
-
648
- this.config = {};
649
-
650
- //load base config from defaults
651
- for(let key in Ajax.defaultConfig){
652
- this.config[key] = Ajax.defaultConfig[key];
653
- }
632
+ Object.assign(ajaxConfig, config);
654
633
  }
634
+
635
+ return ajaxConfig;
655
636
  }
656
-
637
+
657
638
  //set request url
658
639
  setUrl(url){
659
640
  this.url = url;
660
641
  }
661
-
642
+
662
643
  //get request url
663
644
  getUrl(){
664
645
  return this.url;
665
646
  }
666
-
647
+
667
648
  //send ajax request
668
- sendRequest(silent){
669
- var url = this.url;
670
-
671
- this._loadDefaultConfig();
672
-
673
- if(this.table.options.ajaxRequesting.call(this.table, this.url, this.params) !== false){
674
- return this.loaderPromise(url, this.config, this.params)
649
+ sendRequest(url, params, config){
650
+ if(this.table.options.ajaxRequesting.call(this.table, url, params) !== false){
651
+ return this.loaderPromise(url, config, params)
675
652
  .then((data)=>{
676
653
  if(this.table.options.ajaxResponse){
677
- data = this.table.options.ajaxResponse.call(this.table, this.url, this.params, data);
654
+ data = this.table.options.ajaxResponse.call(this.table, url, params, data);
678
655
  }
679
-
656
+
680
657
  return data;
681
658
  });
682
659
  }else {
@@ -1370,6 +1347,10 @@ class Cell extends CoreFeature{
1370
1347
 
1371
1348
  this.cellRendered();
1372
1349
 
1350
+ if(this.column.definition.cellEdited){
1351
+ this.column.definition.cellEdited.call(this.table, this.getComponent());
1352
+ }
1353
+
1373
1354
  this.dispatchExternal("cellEdited", this.getComponent());
1374
1355
 
1375
1356
  if(this.subscribedExternal("dataChanged")){
@@ -1381,7 +1362,7 @@ class Cell extends CoreFeature{
1381
1362
  setValueProcessData(value, mutate){
1382
1363
  var changed = false;
1383
1364
 
1384
- if(this.value != value){
1365
+ if(this.value !== value){
1385
1366
 
1386
1367
  changed = true;
1387
1368
 
@@ -1529,6 +1510,10 @@ class ColumnComponent {
1529
1510
  return this._column.getField();
1530
1511
  }
1531
1512
 
1513
+ getTitleDownload() {
1514
+ return this._column.getTitleDownload();
1515
+ }
1516
+
1532
1517
  getCells(){
1533
1518
  var cells = [];
1534
1519
 
@@ -1648,7 +1633,7 @@ class ColumnComponent {
1648
1633
  }
1649
1634
  }
1650
1635
 
1651
- var defaultOptions = {
1636
+ var defaultColumnOptions = {
1652
1637
  "title": undefined,
1653
1638
  "field": undefined,
1654
1639
  "columns": undefined,
@@ -1658,6 +1643,7 @@ var defaultOptions = {
1658
1643
  "width": undefined,
1659
1644
  "minWidth": 40,
1660
1645
  "maxWidth": undefined,
1646
+ "maxInitialWidth": undefined,
1661
1647
  "tooltip": undefined,
1662
1648
  "cssClass": undefined,
1663
1649
  "variableHeight": undefined,
@@ -1693,6 +1679,7 @@ class Column$1 extends CoreFeature{
1693
1679
  this.getFieldValue = "";
1694
1680
  this.setFieldValue = "";
1695
1681
 
1682
+ this.titleDownload = null;
1696
1683
  this.titleFormatterRendered = false;
1697
1684
 
1698
1685
  this.mapDefinitions();
@@ -1705,6 +1692,7 @@ class Column$1 extends CoreFeature{
1705
1692
  this.widthStyled = ""; //column width prestyled to improve render efficiency
1706
1693
  this.maxWidth = null; //column maximum width
1707
1694
  this.maxWidthStyled = ""; //column maximum prestyled to improve render efficiency
1695
+ this.maxInitialWidth = null;
1708
1696
  this.minWidth = null; //column minimum width
1709
1697
  this.minWidthStyled = ""; //column minimum prestyled to improve render efficiency
1710
1698
  this.widthFixed = false; //user has specified a width for this column
@@ -1810,7 +1798,7 @@ class Column$1 extends CoreFeature{
1810
1798
  var def = this.definition;
1811
1799
 
1812
1800
  //set header tooltips
1813
- var tooltip = typeof def.headerTooltip === "undefined" ? def.tooltip : def.headerTooltip;
1801
+ var tooltip = def.headerTooltip;
1814
1802
 
1815
1803
  if(tooltip){
1816
1804
  if(tooltip === true){
@@ -1983,6 +1971,10 @@ class Column$1 extends CoreFeature{
1983
1971
  //set min width if present
1984
1972
  this.setMinWidth(parseInt(def.minWidth));
1985
1973
 
1974
+ if (def.maxInitialWidth) {
1975
+ this.maxInitialWidth = parseInt(def.maxInitialWidth);
1976
+ }
1977
+
1986
1978
  if(def.maxWidth){
1987
1979
  this.setMaxWidth(parseInt(def.maxWidth));
1988
1980
  }
@@ -2233,6 +2225,10 @@ class Column$1 extends CoreFeature{
2233
2225
  return this.field;
2234
2226
  }
2235
2227
 
2228
+ getTitleDownload() {
2229
+ return this.titleDownload;
2230
+ }
2231
+
2236
2232
  //return the first column in a group
2237
2233
  getFirstColumn(){
2238
2234
  if(!this.isGroup){
@@ -2365,7 +2361,7 @@ class Column$1 extends CoreFeature{
2365
2361
  cell.hide();
2366
2362
  });
2367
2363
 
2368
- this.dispatch("column-hide", this);
2364
+ this.dispatch("column-hide", this, responsiveToggle);
2369
2365
 
2370
2366
  if(!silent){
2371
2367
  this.dispatchExternal("columnVisibilityChanged", this.getComponent(), false);
@@ -2485,7 +2481,7 @@ class Column$1 extends CoreFeature{
2485
2481
  }
2486
2482
 
2487
2483
  getHeight(){
2488
- return this.element.offsetHeight;
2484
+ return Math.ceil(this.element.getBoundingClientRect().height);
2489
2485
  }
2490
2486
 
2491
2487
  setMinWidth(minWidth){
@@ -2589,18 +2585,19 @@ class Column$1 extends CoreFeature{
2589
2585
 
2590
2586
  //set width if present
2591
2587
  if(typeof this.definition.width !== "undefined" && !force){
2588
+ // maxInitialWidth ignored here as width specified
2592
2589
  this.setWidth(this.definition.width);
2593
2590
  }
2594
2591
 
2595
2592
  this.dispatch("column-width-fit-before", this);
2596
2593
 
2597
- this.fitToData();
2594
+ this.fitToData(force);
2598
2595
 
2599
2596
  this.dispatch("column-width-fit-after", this);
2600
2597
  }
2601
2598
 
2602
2599
  //set column width to maximum cell width for non group columns
2603
- fitToData(){
2600
+ fitToData(force){
2604
2601
  if(this.isGroup){
2605
2602
  return;
2606
2603
  }
@@ -2625,7 +2622,11 @@ class Column$1 extends CoreFeature{
2625
2622
  });
2626
2623
 
2627
2624
  if(maxWidth){
2628
- this.setWidthActual(maxWidth + 1);
2625
+ var setTo = maxWidth + 1;
2626
+ if (this.maxInitialWidth && !force) {
2627
+ setTo = Math.min(setTo, this.maxInitialWidth);
2628
+ }
2629
+ this.setWidthActual(setTo);
2629
2630
  }
2630
2631
  }
2631
2632
  }
@@ -2679,7 +2680,7 @@ class Column$1 extends CoreFeature{
2679
2680
  }
2680
2681
  }
2681
2682
 
2682
- Column$1.defaultOptionList = defaultOptions;
2683
+ Column$1.defaultOptionList = defaultColumnOptions;
2683
2684
 
2684
2685
  //public row object
2685
2686
  class RowComponent$1 {
@@ -2854,12 +2855,12 @@ class Row extends CoreFeature{
2854
2855
 
2855
2856
  this.dispatch("row-layout", this);
2856
2857
 
2858
+ this.initialized = true;
2859
+
2857
2860
  if(this.table.options.rowFormatter){
2858
2861
  this.table.options.rowFormatter(this.getComponent());
2859
2862
  }
2860
2863
 
2861
- this.initialized = true;
2862
-
2863
2864
  this.dispatch("row-layout-after", this);
2864
2865
  }else {
2865
2866
  this.table.columnManager.renderer.rerenderRowCells(this);
@@ -3323,8 +3324,9 @@ class ColumnCalcs extends Module{
3323
3324
  this.subscribe("row-added", this.rowsUpdated.bind(this));
3324
3325
  this.subscribe("column-moved", this.recalcActiveRows.bind(this));
3325
3326
  this.subscribe("column-add", this.recalcActiveRows.bind(this));
3326
- this.subscribe("data-refeshed", this.recalcActiveRows.bind(this));
3327
+ this.subscribe("data-refreshed", this.recalcActiveRows.bind(this));
3327
3328
  this.subscribe("table-redraw", this.tableRedraw.bind(this));
3329
+ this.subscribe("rows-visible", this.visibleRows.bind(this));
3328
3330
 
3329
3331
  this.registerTableFunction("getCalcResults", this.getResults.bind(this));
3330
3332
  this.registerTableFunction("recalc", this.userRecalc.bind(this));
@@ -3350,6 +3352,18 @@ class ColumnCalcs extends Module{
3350
3352
  ///////// Internal Logic //////////
3351
3353
  ///////////////////////////////////
3352
3354
 
3355
+ visibleRows(viewable, rows){
3356
+ if(this.topRow){
3357
+ rows.unshift(this.topRow);
3358
+ }
3359
+
3360
+ if(this.botRow){
3361
+ rows.push(this.botRow);
3362
+ }
3363
+
3364
+ return rows;
3365
+ }
3366
+
3353
3367
  rowsUpdated(row){
3354
3368
  if(this.table.options.groupBy){
3355
3369
  this.recalcRowGroup(this);
@@ -3626,7 +3640,7 @@ class ColumnCalcs extends Module{
3626
3640
 
3627
3641
  row.getComponent = () => {
3628
3642
  if(!row.component){
3629
- row.component = new CalcComponent(this);
3643
+ row.component = new CalcComponent(row);
3630
3644
  }
3631
3645
 
3632
3646
  return row.component;
@@ -3803,17 +3817,16 @@ class DataTree extends Module{
3803
3817
  this.registerComponentFunction("row", "getTreeParent", this.getTreeParent.bind(this));
3804
3818
  this.registerComponentFunction("row", "getTreeChildren", this.getRowChildren.bind(this));
3805
3819
  this.registerComponentFunction("row", "addTreeChild", this.addTreeChildRow.bind(this));
3820
+ this.registerComponentFunction("row", "isTreeExpanded", this.isRowExpanded.bind(this));
3806
3821
  }
3807
3822
 
3808
3823
  initialize(){
3809
3824
  if(this.table.options.dataTree){
3810
3825
  var dummyEl = null,
3811
- firstCol = this.table.columnManager.getFirstVisibileColumn(),
3812
3826
  options = this.table.options;
3813
3827
 
3814
3828
  this.field = options.dataTreeChildField;
3815
3829
  this.indent = options.dataTreeChildIndent;
3816
- this.elementField = options.dataTreeElementColumn || (firstCol ? firstCol.field : false);
3817
3830
 
3818
3831
  if(options.dataTreeBranchElement){
3819
3832
 
@@ -3882,15 +3895,23 @@ class DataTree extends Module{
3882
3895
 
3883
3896
  this.subscribe("row-init", this.initializeRow.bind(this));
3884
3897
  this.subscribe("row-layout-after", this.layoutRow.bind(this));
3885
- this.subscribe("row-relayout", this.layoutRow.bind(this));
3886
3898
  this.subscribe("row-deleted", this.rowDelete.bind(this),0);
3887
3899
  this.subscribe("row-data-changed", this.rowDataChanged.bind(this), 10);
3900
+ this.subscribe("cell-value-updated", this.cellValueChanged.bind(this));
3901
+ this.subscribe("edit-cancelled", this.cellValueChanged.bind(this));
3888
3902
  this.subscribe("column-moving-rows", this.columnMoving.bind(this));
3903
+ this.subscribe("table-built", this.initializeElementField.bind(this));
3889
3904
 
3890
3905
  this.registerDisplayHandler(this.getRows.bind(this), 30);
3891
3906
  }
3892
3907
  }
3893
3908
 
3909
+ initializeElementField(){
3910
+ var firstCol = this.table.columnManager.getFirstVisibleColumn();
3911
+
3912
+ this.elementField = this.table.options.dataTreeElementColumn || (firstCol ? firstCol.field : false);
3913
+ }
3914
+
3894
3915
  getRowChildren(row){
3895
3916
  return this.getTreeChildren(row, true);
3896
3917
  }
@@ -3916,6 +3937,14 @@ class DataTree extends Module{
3916
3937
  }
3917
3938
  }
3918
3939
 
3940
+ cellValueChanged(cell){
3941
+ var field = cell.column.getField();
3942
+
3943
+ if(field === this.elementField){
3944
+ this.layoutRow(cell.row);
3945
+ }
3946
+ }
3947
+
3919
3948
  initializeRow(row){
3920
3949
  var childArray = row.getData()[this.field];
3921
3950
  var isArray = Array.isArray(childArray);
@@ -4161,6 +4190,10 @@ class DataTree extends Module{
4161
4190
  }
4162
4191
  }
4163
4192
 
4193
+ isRowExpanded(row){
4194
+ return row.modules.dataTree.open;
4195
+ }
4196
+
4164
4197
  getTreeParent(row){
4165
4198
  return row.modules.dataTree.parent ? row.modules.dataTree.parent.getComponent() : false;
4166
4199
  }
@@ -4320,17 +4353,12 @@ class DataTree extends Module{
4320
4353
  return output;
4321
4354
  }
4322
4355
 
4323
- checkForRestyle(cell){
4324
- if(!cell.row.cells.indexOf(cell)){
4325
- this.layoutRow(cell.row);
4326
- }
4327
- }
4328
-
4329
4356
  getChildField(){
4330
4357
  return this.field;
4331
4358
  }
4332
4359
 
4333
4360
  redrawNeeded(data){
4361
+ console.log("needed?", data);
4334
4362
  return (this.field ? typeof data[this.field] !== "undefined" : false) || (this.elementField ? typeof data[this.elementField] !== "undefined" : false);
4335
4363
  }
4336
4364
  }
@@ -4421,7 +4449,7 @@ function json(list, options, setFileContents){
4421
4449
  case "row":
4422
4450
  row.columns.forEach((col) => {
4423
4451
  if(col){
4424
- item[col.component.getField()] = col.value;
4452
+ item[col.component.getTitleDownload() || col.component.getField()] = col.value;
4425
4453
  }
4426
4454
  });
4427
4455
 
@@ -4513,8 +4541,6 @@ function pdf(list, options, setFileContents){
4513
4541
  }
4514
4542
 
4515
4543
  rowData.push(cell);
4516
- }else {
4517
- rowData.push("");
4518
4544
  }
4519
4545
  });
4520
4546
 
@@ -4577,7 +4603,9 @@ function xlsx(list, options, setFileContents){
4577
4603
  rowData.push(!(col.value instanceof Date) && typeof col.value === "object" ? JSON.stringify(col.value) : col.value);
4578
4604
 
4579
4605
  if(col.width > 1 || col.height > -1){
4580
- merges.push({s:{r:i,c:j},e:{r:i + col.height - 1,c:j + col.width - 1}});
4606
+ if(col.height > 1 || col.width > 1){
4607
+ merges.push({s:{r:i,c:j},e:{r:i + col.height - 1,c:j + col.width - 1}});
4608
+ }
4581
4609
  }
4582
4610
  }else {
4583
4611
  rowData.push("");
@@ -4587,7 +4615,6 @@ function xlsx(list, options, setFileContents){
4587
4615
  rows.push(rowData);
4588
4616
  });
4589
4617
 
4590
-
4591
4618
  //convert rows to worksheet
4592
4619
  XLSX.utils.sheet_add_aoa(worksheet, rows);
4593
4620
 
@@ -4653,9 +4680,43 @@ function html(list, options, setFileContents){
4653
4680
  }
4654
4681
  }
4655
4682
 
4683
+ function jsonLines (list, options, setFileContents) {
4684
+ const fileContents = [];
4685
+
4686
+ list.forEach((row) => {
4687
+ const item = {};
4688
+
4689
+ switch (row.type) {
4690
+ case "header":
4691
+ break;
4692
+
4693
+ case "group":
4694
+ console.warn("Download Warning - JSON downloader cannot process row groups");
4695
+ break;
4696
+
4697
+ case "calc":
4698
+ console.warn("Download Warning - JSON downloader cannot process column calculations");
4699
+ break;
4700
+
4701
+ case "row":
4702
+ row.columns.forEach((col) => {
4703
+ if (col) {
4704
+ item[col.component.getTitleDownload() || col.component.getField()] = col.value;
4705
+ }
4706
+ });
4707
+
4708
+ fileContents.push(JSON.stringify(item));
4709
+ break;
4710
+ }
4711
+ });
4712
+
4713
+ setFileContents(fileContents.join("\n"), "application/x-ndjson");
4714
+ }
4715
+
4656
4716
  var defaultDownloaders = {
4657
4717
  csv:csv,
4658
4718
  json:json,
4719
+ jsonLines:jsonLines,
4659
4720
  pdf:pdf,
4660
4721
  xlsx:xlsx,
4661
4722
  html:html,
@@ -6422,8 +6483,8 @@ function star(cell, onRendered, success, cancel, editorParams){
6422
6483
  //draggable progress bar
6423
6484
  function progress(cell, onRendered, success, cancel, editorParams){
6424
6485
  var element = cell.getElement(),
6425
- max = typeof editorParams.max === "undefined" ? ( element.getElementsByTagName("div")[0]?.getAttribute("max") || 100) : editorParams.max,
6426
- min = typeof editorParams.min === "undefined" ? ( element.getElementsByTagName("div")[0]?.getAttribute("min") || 0) : editorParams.min,
6486
+ max = typeof editorParams.max === "undefined" ? ((element.getElementsByTagName("div")[0] && element.getElementsByTagName("div")[0].getAttribute("max")) || 100) : editorParams.max,
6487
+ min = typeof editorParams.min === "undefined" ? ((element.getElementsByTagName("div")[0] && element.getElementsByTagName("div")[0].getAttribute("min")) || 0) : editorParams.min,
6427
6488
  percent = (max - min) / 100,
6428
6489
  value = cell.getValue() || 0,
6429
6490
  handle = document.createElement("div"),
@@ -6698,12 +6759,12 @@ class Edit extends Module{
6698
6759
  this.subscribe("row-deleting", this.rowDeleteCheck.bind(this));
6699
6760
  this.subscribe("data-refeshing", this.cancelEdit.bind(this));
6700
6761
 
6701
- this.subscribe("keybinding-nav-prev", this.navigatePrev.bind(this));
6762
+ this.subscribe("keybinding-nav-prev", this.navigatePrev.bind(this, undefined));
6702
6763
  this.subscribe("keybinding-nav-next", this.keybindingNavigateNext.bind(this));
6703
- this.subscribe("keybinding-nav-left", this.navigateLeft.bind(this));
6704
- this.subscribe("keybinding-nav-right", this.navigateRight.bind(this));
6705
- this.subscribe("keybinding-nav-up", this.navigateUp.bind(this));
6706
- this.subscribe("keybinding-nav-down", this.navigateDown.bind(this));
6764
+ this.subscribe("keybinding-nav-left", this.navigateLeft.bind(this, undefined));
6765
+ this.subscribe("keybinding-nav-right", this.navigateRight.bind(this, undefined));
6766
+ this.subscribe("keybinding-nav-up", this.navigateUp.bind(this, undefined));
6767
+ this.subscribe("keybinding-nav-down", this.navigateDown.bind(this, undefined));
6707
6768
  }
6708
6769
 
6709
6770
 
@@ -6716,9 +6777,9 @@ class Edit extends Module{
6716
6777
  newRow = this.options("tabEndNewRow");
6717
6778
 
6718
6779
  if(cell){
6719
- if(!this.navigateNext(e)){
6780
+ if(!this.navigateNext(cell, e)){
6720
6781
  if(newRow){
6721
- cell.getElement().firstChild.blur();
6782
+ // cell.getElement().firstChild.blur();
6722
6783
 
6723
6784
  if(newRow === true){
6724
6785
  newRow = this.table.addRow({});
@@ -6732,7 +6793,7 @@ class Edit extends Module{
6732
6793
 
6733
6794
  newRow.then(() => {
6734
6795
  setTimeout(() => {
6735
- nav.next();
6796
+ cell.getComponent().navigateNext();
6736
6797
  });
6737
6798
  });
6738
6799
  }
@@ -6762,7 +6823,7 @@ class Edit extends Module{
6762
6823
  ///////////////////////////////////
6763
6824
  clearCellEdited(cells){
6764
6825
  if(!cells){
6765
- cells = this.modules.edit.getEditedCells();
6826
+ cells = this.table.modules.edit.getEditedCells();
6766
6827
  }
6767
6828
 
6768
6829
  if(!Array.isArray(cells)){
@@ -6770,13 +6831,12 @@ class Edit extends Module{
6770
6831
  }
6771
6832
 
6772
6833
  cells.forEach((cell) => {
6773
- this.modules.edit.clearEdited(cell._getSelf());
6834
+ this.table.modules.edit.clearEdited(cell._getSelf());
6774
6835
  });
6775
6836
  }
6776
6837
 
6777
- navigatePrev(e){
6778
- var cell = this.currentCell,
6779
- nextCell, prevRow;
6838
+ navigatePrev(cell = this.currentCell, e){
6839
+ var nextCell, prevRow;
6780
6840
 
6781
6841
  if(cell){
6782
6842
 
@@ -6805,9 +6865,8 @@ class Edit extends Module{
6805
6865
  return false;
6806
6866
  }
6807
6867
 
6808
- navigateNext(e){
6809
- var cell = this.currentCell,
6810
- nextCell, nextRow;
6868
+ navigateNext(cell = this.currentCell, e){
6869
+ var nextCell, nextRow;
6811
6870
 
6812
6871
  if(cell){
6813
6872
 
@@ -6836,9 +6895,8 @@ class Edit extends Module{
6836
6895
  return false;
6837
6896
  }
6838
6897
 
6839
- navigateLeft(e){
6840
- var cell = this.currentCell,
6841
- index, nextCell;
6898
+ navigateLeft(cell = this.currentCell, e){
6899
+ var index, nextCell;
6842
6900
 
6843
6901
  if(cell){
6844
6902
 
@@ -6858,9 +6916,8 @@ class Edit extends Module{
6858
6916
  return false;
6859
6917
  }
6860
6918
 
6861
- navigateRight(e){
6862
- var cell = this.currentCell,
6863
- index, nextCell;
6919
+ navigateRight(cell = this.currentCell, e){
6920
+ var index, nextCell;
6864
6921
 
6865
6922
  if(cell){
6866
6923
 
@@ -6880,9 +6937,8 @@ class Edit extends Module{
6880
6937
  return false;
6881
6938
  }
6882
6939
 
6883
- navigateUp(e){
6884
- var cell = this.currentCell,
6885
- index, nextRow;
6940
+ navigateUp(cell = this.currentCell, e){
6941
+ var index, nextRow;
6886
6942
 
6887
6943
  if(cell){
6888
6944
 
@@ -6902,9 +6958,8 @@ class Edit extends Module{
6902
6958
  return false;
6903
6959
  }
6904
6960
 
6905
- navigateDown(e){
6906
- var cell = this.currentCell,
6907
- index, nextRow;
6961
+ navigateDown(cell = this.currentCell, e){
6962
+ var index, nextRow;
6908
6963
 
6909
6964
  if(cell){
6910
6965
 
@@ -7054,14 +7109,15 @@ class Edit extends Module{
7054
7109
  cellEl = cell.getElement();
7055
7110
 
7056
7111
  if(cancel){
7057
- if(cell.validate){
7058
- cell.validate();
7112
+ if(cell.column.modules.validate && this.table.modExists("validate")){
7113
+ this.table.modules.validate.cellValidate(cell);
7059
7114
  }
7060
7115
  }else {
7061
7116
  cellEl.classList.remove("tabulator-validation-fail");
7062
7117
  }
7063
7118
 
7064
7119
  cellEl.classList.remove("tabulator-editing");
7120
+
7065
7121
  while(cellEl.firstChild) cellEl.removeChild(cellEl.firstChild);
7066
7122
 
7067
7123
  cell.row.getElement().classList.remove("tabulator-row-editing");
@@ -7085,6 +7141,7 @@ class Edit extends Module{
7085
7141
  cell.column.definition.cellEditCancelled.call(this.table, component);
7086
7142
  }
7087
7143
 
7144
+ this.dispatch("edit-cancelled", cell);
7088
7145
  this.dispatchExternal("cellEditCancelled", component);
7089
7146
  }
7090
7147
  }
@@ -7215,10 +7272,6 @@ class Edit extends Module{
7215
7272
 
7216
7273
  cell.setValue(value, true);
7217
7274
 
7218
- if(self.table.options.dataTree && self.table.modExists("dataTree")){
7219
- self.table.modules.dataTree.checkForRestyle(cell);
7220
- }
7221
-
7222
7275
  if(valid !== true){
7223
7276
  element.classList.add("tabulator-validation-fail");
7224
7277
  self.table.externalEvents.dispatch("validationFailed", cell.getComponent(), value, valid);
@@ -7241,10 +7294,6 @@ class Edit extends Module{
7241
7294
  function cancel(){
7242
7295
  if(self.currentCell === cell){
7243
7296
  self.cancelEdit();
7244
-
7245
- if(self.table.options.dataTree && self.table.modExists("dataTree")){
7246
- self.table.modules.dataTree.checkForRestyle(cell);
7247
- }
7248
7297
  }
7249
7298
  }
7250
7299
 
@@ -7452,7 +7501,7 @@ class Export extends Module{
7452
7501
  switch(range){
7453
7502
  case true:
7454
7503
  case "visible":
7455
- rows = this.table.rowManager.getVisibleRows(true);
7504
+ rows = this.table.rowManager.getVisibleRows(false, true);
7456
7505
  break;
7457
7506
 
7458
7507
  case "all":
@@ -8484,7 +8533,7 @@ class Filter extends Module{
8484
8533
 
8485
8534
  params = column.definition.headerFilterParams || {};
8486
8535
 
8487
- params = typeof params === "function" ? params.call(self.table) : params;
8536
+ params = typeof params === "function" ? params.call(self.table, cellWrapper) : params;
8488
8537
 
8489
8538
  editorElement = editor.call(this.table.modules.edit, cellWrapper, function(){}, success, cancel, params);
8490
8539
 
@@ -8655,7 +8704,7 @@ class Filter extends Module{
8655
8704
  if(this.table.options.filterMode === "remote"){
8656
8705
  this.reloadData();
8657
8706
  }else {
8658
- this.refreshData();
8707
+ this.refreshData(true);
8659
8708
  }
8660
8709
  }
8661
8710
 
@@ -9173,7 +9222,7 @@ function datetime(cell, formatterParams, onRendered){
9173
9222
  var value = cell.getValue();
9174
9223
 
9175
9224
  if(typeof DT != "undefined"){
9176
- var newDatetime = (window.DateTime || luxon.DateTime).fromFormat(value, inputFormat);
9225
+ var newDatetime = inputFormat === "iso" ? DT.fromISO(String(value)) : DT.fromFormat(String(value), inputFormat);
9177
9226
 
9178
9227
  if(newDatetime.isValid){
9179
9228
 
@@ -9184,7 +9233,7 @@ function datetime(cell, formatterParams, onRendered){
9184
9233
  return newDatetime.toFormat(outputFormat);
9185
9234
  }else {
9186
9235
 
9187
- if(invalid === true){
9236
+ if(invalid === true || !value){
9188
9237
  return value;
9189
9238
  }else if(typeof invalid === "function"){
9190
9239
  return invalid(value);
@@ -9208,7 +9257,8 @@ function datetimediff (cell, formatterParams, onRendered) {
9208
9257
  var value = cell.getValue();
9209
9258
 
9210
9259
  if(typeof DT != "undefined"){
9211
- var newDatetime = DT.fromFormat(value, inputFormat);
9260
+
9261
+ var newDatetime = inputFormat === "iso" ? DT.fromISO(String(value)) : DT.fromFormat(String(value), inputFormat);
9212
9262
 
9213
9263
  if (newDatetime.isValid){
9214
9264
  if(humanize);else {
@@ -9821,7 +9871,7 @@ class FrozenColumns extends Module{
9821
9871
  this.subscribe("cell-layout", this.layoutCell.bind(this));
9822
9872
  this.subscribe("column-init", this.initializeColumn.bind(this));
9823
9873
  this.subscribe("column-width", this.layout.bind(this));
9824
- this.subscribe("row-layout-before", this.layoutRow.bind(this));
9874
+ this.subscribe("row-layout-after", this.layoutRow.bind(this));
9825
9875
  this.subscribe("table-layout", this.layout.bind(this));
9826
9876
  this.subscribe("scroll-horizontal", this.scrollHorizontal.bind(this));
9827
9877
  this.subscribe("columns-loading", this.reset.bind(this));
@@ -10105,6 +10155,7 @@ class FrozenRows extends Module{
10105
10155
  this.table.columnManager.getElement().insertBefore(this.topElement, this.table.columnManager.headersElement.nextSibling);
10106
10156
 
10107
10157
  this.subscribe("row-deleting", this.detachRow.bind(this));
10158
+ this.subscribe("rows-visible", this.visibleRows.bind(this));
10108
10159
 
10109
10160
  this.registerDisplayHandler(this.getRows.bind(this), 10);
10110
10161
  }
@@ -10118,6 +10169,14 @@ class FrozenRows extends Module{
10118
10169
  return !!this.rows.length;
10119
10170
  }
10120
10171
 
10172
+ visibleRows(viewable, rows){
10173
+ this.rows.forEach((row) => {
10174
+ rows.push(row);
10175
+ });
10176
+
10177
+ return rows;
10178
+ }
10179
+
10121
10180
  //filter frozen rows out of display data
10122
10181
  getRows(rows){
10123
10182
  var output = rows.slice(0);
@@ -10280,6 +10339,7 @@ class Group{
10280
10339
  this.groups = [];
10281
10340
  this.groupList = [];
10282
10341
  this.generator = generator;
10342
+ this.element = false;
10283
10343
  this.elementContents = false;
10284
10344
  this.height = 0;
10285
10345
  this.outerHeight = 0;
@@ -10305,10 +10365,16 @@ class Group{
10305
10365
  group.wipe();
10306
10366
  });
10307
10367
  }else {
10308
- this.element = false;
10309
- this.arrowElement = false;
10310
- this.elementContents = false;
10368
+ this.rows.forEach((row) => {
10369
+ if(row.modules){
10370
+ delete row.modules.group;
10371
+ }
10372
+ });
10311
10373
  }
10374
+
10375
+ this.element = false;
10376
+ this.arrowElement = false;
10377
+ this.elementContents = false;
10312
10378
  }
10313
10379
 
10314
10380
  createElements(){
@@ -10341,67 +10407,7 @@ class Group{
10341
10407
  }
10342
10408
 
10343
10409
  addBindings(){
10344
- var dblTap, tapHold, tap, toggleElement;
10345
-
10346
- if ((this.groupManager.table.options.groupContextMenu || this.groupManager.table.options.groupClickMenu) && this.groupManager.table.modExists("menu")){
10347
- this.groupManager.table.modules.menu.initializeGroup.call(this.groupManager.table.modules.menu, this);
10348
- }
10349
-
10350
- if (this.groupManager.table.options.groupTap){
10351
- tap = false;
10352
-
10353
- this.element.addEventListener("touchstart", (e) => {
10354
- tap = true;
10355
- }, {passive: true});
10356
-
10357
- this.element.addEventListener("touchend", (e) => {
10358
- if(tap){
10359
- this.groupManager.table.options.groupTap(e, this.getComponent());
10360
- }
10361
-
10362
- tap = false;
10363
- });
10364
- }
10365
-
10366
- if (this.groupManager.table.options.groupDblTap){
10367
- dblTap = null;
10368
-
10369
- this.element.addEventListener("touchend", (e) => {
10370
- if(dblTap){
10371
- clearTimeout(dblTap);
10372
- dblTap = null;
10373
-
10374
- this.groupManager.table.options.groupDblTap(e, this.getComponent());
10375
- }else {
10376
-
10377
- dblTap = setTimeout(() => {
10378
- clearTimeout(dblTap);
10379
- dblTap = null;
10380
- }, 300);
10381
- }
10382
- });
10383
- }
10384
-
10385
- if (this.groupManager.table.options.groupTapHold){
10386
- tapHold = null;
10387
-
10388
- this.element.addEventListener("touchstart", (e) => {
10389
- clearTimeout(tapHold);
10390
-
10391
- tapHold = setTimeout(() => {
10392
- clearTimeout(tapHold);
10393
- tapHold = null;
10394
- tap = false;
10395
- this.groupManager.table.options.groupTapHold(e, this.getComponent());
10396
- }, 1000);
10397
-
10398
- }, {passive: true});
10399
-
10400
- this.element.addEventListener("touchend", (e) => {
10401
- clearTimeout(tapHold);
10402
- tapHold = null;
10403
- });
10404
- }
10410
+ var toggleElement;
10405
10411
 
10406
10412
  if(this.groupManager.table.options.groupToggleElement){
10407
10413
  toggleElement = this.groupManager.table.options.groupToggleElement == "arrow" ? this.arrowElement : this.element;
@@ -10530,7 +10536,7 @@ class Group{
10530
10536
  }
10531
10537
 
10532
10538
  this.generateGroupHeaderContents();
10533
-
10539
+
10534
10540
  if(this.groupManager.table.modExists("columnCalcs") && this.groupManager.table.options.columnCalcs != "table"){
10535
10541
  this.groupManager.table.modules.columnCalcs.recalcGroup(this);
10536
10542
  }
@@ -10710,7 +10716,7 @@ class Group{
10710
10716
 
10711
10717
  this.element.classList.add("tabulator-group-visible");
10712
10718
 
10713
- var prev = this.getElement();
10719
+ var prev = this.generateElement();
10714
10720
 
10715
10721
  if(this.groupList.length){
10716
10722
  this.groupList.forEach((group) => {
@@ -10828,7 +10834,11 @@ class Group{
10828
10834
  ////////////// Standard Row Functions //////////////
10829
10835
 
10830
10836
  getElement(){
10831
- this.addBindingsd = false;
10837
+ return this.elementContents ? this.element : this.generateElement();
10838
+ }
10839
+
10840
+ generateElement(){
10841
+ this.addBindings = false;
10832
10842
 
10833
10843
  this._visSet();
10834
10844
 
@@ -10956,13 +10966,13 @@ class GroupRows extends Module{
10956
10966
  initialize(){
10957
10967
  if(this.table.options.groupBy){
10958
10968
 
10959
- this.configureGroupSetup();
10960
-
10961
10969
  if(this.table.options.groupUpdateOnCellEdit){
10962
10970
  this.subscribe("cell-value-updated", this.cellUpdated.bind(this));
10963
10971
  this.subscribe("row-data-changed", this.reassignRowToGroup.bind(this), 0);
10964
10972
  }
10965
10973
 
10974
+ this.subscribe("table-built", this.configureGroupSetup.bind(this));
10975
+
10966
10976
  this.subscribe("row-deleting", this.rowDeleting.bind(this));
10967
10977
  this.subscribe("row-deleted", this.rowsUpdated.bind(this));
10968
10978
  this.subscribe("scroll-horizontal", this.scrollHeaders.bind(this));
@@ -11133,7 +11143,12 @@ class GroupRows extends Module{
11133
11143
 
11134
11144
  setGroupBy(groups){
11135
11145
  this.table.options.groupBy = groups;
11136
- this.configureGroupSetup();
11146
+ if(!this.initialized){
11147
+ this.initialize();
11148
+ }else {
11149
+ this.configureGroupSetup();
11150
+ }
11151
+
11137
11152
  this.refreshData();
11138
11153
 
11139
11154
  this.trackChanges();
@@ -11733,7 +11748,7 @@ class HtmlTableImport extends Module{
11733
11748
 
11734
11749
  rows = rows ? rows.getElementsByTagName("tr") : [];
11735
11750
 
11736
- //check for tablator inline options
11751
+ //check for Tabulator inline options
11737
11752
  this._extractOptions(element, options);
11738
11753
 
11739
11754
  if(headers.length){
@@ -11772,7 +11787,7 @@ class HtmlTableImport extends Module{
11772
11787
  //extract tabulator attribute options
11773
11788
  _extractOptions(element, options, defaultOptions){
11774
11789
  var attributes = element.attributes;
11775
- var optionsArr = defaultOptions ? Object.assign([], defaultOptions) : Object.keys(options);
11790
+ var optionsArr = defaultOptions ? Object.keys(defaultOptions) : Object.keys(options);
11776
11791
  var optionsList = {};
11777
11792
 
11778
11793
  optionsArr.forEach((item) => {
@@ -11839,11 +11854,8 @@ class HtmlTableImport extends Module{
11839
11854
  col.width = width;
11840
11855
  }
11841
11856
 
11842
- //check for tablator inline options
11843
- header.attributes;
11844
-
11845
- // //check for tablator inline options
11846
- this._extractOptions(header, col, Column$1.prototype.defaultOptionList);
11857
+ //check for Tabulator inline options
11858
+ this._extractOptions(header, col, this.table.columnManager.optionsList.registeredDefaults);
11847
11859
 
11848
11860
  this.fieldIndex[index] = col.field;
11849
11861
 
@@ -11879,40 +11891,307 @@ class HtmlTableImport extends Module{
11879
11891
 
11880
11892
  HtmlTableImport.moduleName = "htmlTableImport";
11881
11893
 
11882
- class Interaction extends Module{
11894
+ function csvImporter(input){
11895
+ var data = [],
11896
+ row = 0,
11897
+ col = 0,
11898
+ inQuote = false;
11899
+
11900
+ //Iterate over each character
11901
+ for (let index = 0; index < input.length; index++) {
11902
+ let char = input[index],
11903
+ nextChar = input[index+1];
11904
+
11905
+ //Initialize empty row
11906
+ if(!data[row]){
11907
+ data[row] = [];
11908
+ }
11883
11909
 
11884
- constructor(table){
11885
- super(table);
11910
+ //Initialize empty column
11911
+ if(!data[row][col]){
11912
+ data[row][col] = "";
11913
+ }
11914
+
11915
+ //Handle quotation mark inside string
11916
+ if (char == '"' && inQuote && nextChar == '"') {
11917
+ data[row][col] += char;
11918
+ index++;
11919
+ continue;
11920
+ }
11921
+
11922
+ //Begin / End Quote
11923
+ if (char == '"') {
11924
+ inQuote = !inQuote;
11925
+ continue;
11926
+ }
11927
+
11928
+ //Next column (if not in quote)
11929
+ if (char == ',' && !inQuote) {
11930
+ col++;
11931
+ continue;
11932
+ }
11933
+
11934
+ //New row if new line and not in quote (CRLF)
11935
+ if (char == '\r' && nextChar == '\n' && !inQuote) {
11936
+ col = 0;
11937
+ row++;
11938
+ index++;
11939
+ continue;
11940
+ }
11941
+
11942
+ //New row if new line and not in quote (CR or LF)
11943
+ if ((char == '\r' || char == '\n') && !inQuote) {
11944
+ col = 0;
11945
+ row++;
11946
+ continue;
11947
+ }
11886
11948
 
11887
- this.eventMap = {
11888
- //row events
11889
- rowClick:"row-click",
11890
- rowDblClick:"row-dblclick",
11891
- rowContext:"row-contextmenu",
11892
- rowMouseEnter:"row-mouseenter",
11893
- rowMouseLeave:"row-mouseleave",
11894
- rowMouseOver:"row-mouseover",
11895
- rowMouseOut:"row-mouseout",
11896
- rowMouseMove:"row-mousemove",
11897
- rowTap:"row",
11898
- rowDblTap:"row",
11899
- rowTapHold:"row",
11949
+ //Normal Character, append to column
11950
+ data[row][col] += char;
11951
+ }
11900
11952
 
11901
- //cell events
11902
- cellClick:"cell-click",
11903
- cellDblClick:"cell-dblclick",
11904
- cellContext:"cell-contextmenu",
11905
- cellMouseEnter:"cell-mouseenter",
11906
- cellMouseLeave:"cell-mouseleave",
11907
- cellMouseOver:"cell-mouseover",
11908
- cellMouseOut:"cell-mouseout",
11909
- cellMouseMove:"cell-mousemove",
11910
- cellTap:"cell",
11911
- cellDblTap:"cell",
11912
- cellTapHold:"cell",
11953
+ return data;
11954
+ }
11955
+
11956
+ function json$1(input){
11957
+ try {
11958
+ return JSON.parse(input);
11959
+ } catch(e) {
11960
+ console.warn("JSON Import Error - File contents is invalid JSON", e);
11961
+ return Promise.reject();
11962
+ }
11963
+ }
11964
+
11965
+ var defaultImporters = {
11966
+ csv:csvImporter,
11967
+ json:json$1,
11968
+ };
11969
+
11970
+ class Import extends Module{
11971
+
11972
+ constructor(table){
11973
+ super(table);
11974
+
11975
+ this.registerTableOption("importFormat");
11976
+ this.registerTableOption("importReader", "text");
11977
+ }
11978
+
11979
+ initialize(){
11980
+ this.registerTableFunction("import", this.importFromFile.bind(this));
11913
11981
 
11914
- //column header events
11915
- headerClick:"column-click",
11982
+ if(this.table.options.importFormat){
11983
+ this.subscribe("data-loading", this.loadDataCheck.bind(this), 10);
11984
+ this.subscribe("data-load", this.loadData.bind(this), 10);
11985
+ }
11986
+ }
11987
+
11988
+ loadDataCheck(data){
11989
+ return typeof data === "string";
11990
+ }
11991
+
11992
+ loadData(data, params, config, silent, previousData){
11993
+ return this.importData(this.lookupImporter(), data)
11994
+ .then(this.structureData.bind(this))
11995
+ .catch((err) => {
11996
+ console.error("Import Error:", err || "Unable to import data");
11997
+ return Promise.reject(err);
11998
+ })
11999
+ }
12000
+
12001
+ lookupImporter(importFormat){
12002
+ var importer;
12003
+
12004
+ if(!importFormat){
12005
+ importFormat = this.table.options.importFormat;
12006
+ }
12007
+
12008
+ if(typeof importFormat === "string"){
12009
+ importer = Import.importers[importFormat];
12010
+ }else {
12011
+ importer = importFormat;
12012
+ }
12013
+
12014
+ if(!importer){
12015
+ console.error("Import Error - Importer not found:", importFormat);
12016
+ }
12017
+
12018
+ return importer;
12019
+ }
12020
+
12021
+ importFromFile(importFormat, extension){
12022
+ var importer = this.lookupImporter(importFormat);
12023
+
12024
+ if(importer){
12025
+ return this.pickFile(extension)
12026
+ .then(this.importData.bind(this, importer))
12027
+ .then(this.structureData.bind(this))
12028
+ .then(this.setData.bind(this))
12029
+ .catch((err) => {
12030
+ console.error("Import Error:", err || "Unable to import file");
12031
+ return Promise.reject(err);
12032
+ })
12033
+ }
12034
+ }
12035
+
12036
+ pickFile(extensions){
12037
+ return new Promise((resolve, reject) => {
12038
+ var input = document.createElement("input");
12039
+ input.type = "file";
12040
+ input.accept = extensions;
12041
+
12042
+ input.addEventListener("change", (e) => {
12043
+ var file = input.files[0],
12044
+ reader = new FileReader();
12045
+
12046
+ switch(this.table.options.importReader){
12047
+ case "buffer":
12048
+ reader.readAsArrayBuffer(file);
12049
+ break;
12050
+
12051
+ case "binary":
12052
+ reader.readAsBinaryString(file);
12053
+ break;
12054
+
12055
+ case "url":
12056
+ reader.readAsDataURL(file);
12057
+ break;
12058
+
12059
+ case "text":
12060
+ default:
12061
+ reader.readAsText(file);
12062
+ }
12063
+
12064
+ reader.onload = (e) => {
12065
+ resolve(reader.result);
12066
+ };
12067
+
12068
+ reader.onerror = (e) => {
12069
+ console.warn("File Load Error - Unable to read file");
12070
+ reject();
12071
+ };
12072
+ });
12073
+
12074
+ input.click();
12075
+ });
12076
+ }
12077
+
12078
+ importData(importer, fileContents){
12079
+ var data = importer.call(this.table, fileContents);
12080
+
12081
+ if(data instanceof Promise){
12082
+ return data;
12083
+ }else {
12084
+ return data ? Promise.resolve(data) : Promise.reject();
12085
+ }
12086
+ }
12087
+
12088
+ structureData(parsedData){
12089
+ var data = [];
12090
+
12091
+ console.log("structure", parsedData);
12092
+
12093
+ if(Array.isArray(parsedData) && parsedData.length && Array.isArray(parsedData[0])){
12094
+ if(this.table.options.autoColumns){
12095
+ data = this.structureArrayToObject(parsedData);
12096
+ }else {
12097
+ data = this.structureArrayToColumns(parsedData);
12098
+ }
12099
+
12100
+ return data;
12101
+ }else {
12102
+ return parsedData;
12103
+ }
12104
+ }
12105
+
12106
+ structureArrayToObject(parsedData){
12107
+ var columns = parsedData.shift();
12108
+
12109
+ var data = parsedData.map((values) => {
12110
+ var row = {};
12111
+
12112
+ columns.forEach((key, i) => {
12113
+ row[key] = values[i];
12114
+ });
12115
+
12116
+ return row;
12117
+ });
12118
+
12119
+ return data;
12120
+ }
12121
+
12122
+ structureArrayToColumns(parsedData){
12123
+ var data = [],
12124
+ columns = this.table.getColumns();
12125
+
12126
+ //remove first row if it is the column names
12127
+ if(columns[0] && parsedData[0][0]){
12128
+ if(columns[0].getDefinition().title === parsedData[0][0]){
12129
+ parsedData.shift();
12130
+ }
12131
+ }
12132
+
12133
+ //convert row arrays to objects
12134
+ parsedData.forEach((rowData) => {
12135
+ var row = {};
12136
+
12137
+ rowData.forEach((value, index) => {
12138
+ var column = columns[index];
12139
+
12140
+ if(column){
12141
+ row[column.getField()] = value;
12142
+ }
12143
+ });
12144
+
12145
+ data.push(row);
12146
+ });
12147
+
12148
+ return data;
12149
+ }
12150
+
12151
+ setData(data){
12152
+ return this.table.setData(data);
12153
+ }
12154
+ }
12155
+
12156
+ Import.moduleName = "import";
12157
+
12158
+ //load defaults
12159
+ Import.importers = defaultImporters;
12160
+
12161
+ class Interaction extends Module{
12162
+
12163
+ constructor(table){
12164
+ super(table);
12165
+
12166
+ this.eventMap = {
12167
+ //row events
12168
+ rowClick:"row-click",
12169
+ rowDblClick:"row-dblclick",
12170
+ rowContext:"row-contextmenu",
12171
+ rowMouseEnter:"row-mouseenter",
12172
+ rowMouseLeave:"row-mouseleave",
12173
+ rowMouseOver:"row-mouseover",
12174
+ rowMouseOut:"row-mouseout",
12175
+ rowMouseMove:"row-mousemove",
12176
+ rowTap:"row",
12177
+ rowDblTap:"row",
12178
+ rowTapHold:"row",
12179
+
12180
+ //cell events
12181
+ cellClick:"cell-click",
12182
+ cellDblClick:"cell-dblclick",
12183
+ cellContext:"cell-contextmenu",
12184
+ cellMouseEnter:"cell-mouseenter",
12185
+ cellMouseLeave:"cell-mouseleave",
12186
+ cellMouseOver:"cell-mouseover",
12187
+ cellMouseOut:"cell-mouseout",
12188
+ cellMouseMove:"cell-mousemove",
12189
+ cellTap:"cell",
12190
+ cellDblTap:"cell",
12191
+ cellTapHold:"cell",
12192
+
12193
+ //column header events
12194
+ headerClick:"column-click",
11916
12195
  headerDblClick:"column-dblclick",
11917
12196
  headerContext:"column-contextmenu",
11918
12197
  headerMouseEnter:"column-mouseenter",
@@ -11959,6 +12238,11 @@ class Interaction extends Module{
11959
12238
  tap:null,
11960
12239
  tapDbl:null,
11961
12240
  tapHold:null,
12241
+ },
12242
+ group:{
12243
+ tap:null,
12244
+ tapDbl:null,
12245
+ tapHold:null,
11962
12246
  }
11963
12247
  };
11964
12248
 
@@ -12189,9 +12473,9 @@ var defaultBindings = {
12189
12473
  scrollPageDown:34,
12190
12474
  scrollToStart:36,
12191
12475
  scrollToEnd:35,
12192
- undo:"ctrl + 90",
12193
- redo:"ctrl + 89",
12194
- copyToClipboard:"ctrl + 67",
12476
+ undo:["ctrl + 90", "meta + 90"],
12477
+ redo:["ctrl + 89", "meta + 89"],
12478
+ copyToClipboard:["ctrl + 67", "meta + 89"],
12195
12479
  };
12196
12480
 
12197
12481
  var defaultActions = {
@@ -12325,7 +12609,7 @@ class Keybindings extends Module{
12325
12609
  this.keyupBinding = false;
12326
12610
  this.keydownBinding = false;
12327
12611
 
12328
- this.registerTableOption("keybindings", []); //array for keybindings
12612
+ this.registerTableOption("keybindings", {}); //array for keybindings
12329
12613
  this.registerTableOption("tabEndNewRow", false); //create new row when tab to end of table
12330
12614
  }
12331
12615
 
@@ -12337,17 +12621,8 @@ class Keybindings extends Module{
12337
12621
  this.pressedKeys = [];
12338
12622
 
12339
12623
  if(bindings !== false){
12340
-
12341
- for(let key in Keybindings.bindings){
12342
- mergedBindings[key] = Keybindings.bindings[key];
12343
- }
12344
-
12345
- if(Object.keys(bindings).length){
12346
-
12347
- for(let key in bindings){
12348
- mergedBindings[key] = bindings[key];
12349
- }
12350
- }
12624
+ Object.assign(mergedBindings, Keybindings.bindings);
12625
+ Object.assign(mergedBindings, bindings);
12351
12626
 
12352
12627
  this.mapBindings(mergedBindings);
12353
12628
  this.bindEvents();
@@ -12365,7 +12640,11 @@ class Keybindings extends Module{
12365
12640
  }
12366
12641
 
12367
12642
  bindings[key].forEach((binding) => {
12368
- this.mapBinding(key, binding);
12643
+ var bindingList = Array.isArray(binding) ? binding : [binding];
12644
+
12645
+ bindingList.forEach((item) => {
12646
+ this.mapBinding(key, item);
12647
+ });
12369
12648
  });
12370
12649
  }
12371
12650
  }else {
@@ -12400,7 +12679,7 @@ class Keybindings extends Module{
12400
12679
  break;
12401
12680
 
12402
12681
  default:
12403
- symbol = parseInt(symbol);
12682
+ symbol = isNaN(symbol) ? symbol.toUpperCase().charCodeAt(0) : parseInt(symbol);
12404
12683
  binding.keys.push(symbol);
12405
12684
 
12406
12685
  if(!this.watchKeys[symbol]){
@@ -12488,164 +12767,193 @@ Keybindings.bindings = defaultBindings;
12488
12767
  Keybindings.actions = defaultActions;
12489
12768
 
12490
12769
  class Menu extends Module{
12491
-
12770
+
12492
12771
  constructor(table){
12493
12772
  super(table);
12494
-
12773
+
12774
+ this.menuContainer = null;
12495
12775
  this.menuElements = [];
12496
12776
  this.blurEvent = this.hideMenu.bind(this);
12497
12777
  this.escEvent = this.escMenu.bind(this);
12498
12778
  this.nestedMenuBlock = false;
12499
12779
  this.positionReversedX = false;
12500
-
12780
+
12781
+ this.currentComponent = null;
12782
+
12783
+ this.columnSubscribers = {};
12784
+
12501
12785
  this.registerTableOption("rowContextMenu", false);
12502
12786
  this.registerTableOption("rowClickMenu", false);
12503
12787
  this.registerTableOption("groupContextMenu", false);
12504
12788
  this.registerTableOption("groupClickMenu", false);
12505
-
12789
+ this.registerTableOption("menuContainer", false);
12790
+
12506
12791
  this.registerColumnOption("headerContextMenu");
12792
+ this.registerColumnOption("headerClickMenu");
12507
12793
  this.registerColumnOption("headerMenu");
12508
12794
  this.registerColumnOption("contextMenu");
12509
12795
  this.registerColumnOption("clickMenu");
12510
12796
  }
12511
-
12797
+
12512
12798
  initialize(){
12513
- this.subscribe("cell-layout", this.layoutCell.bind(this));
12799
+ this.lookupMenuContainer();
12800
+
12801
+ this.initializeRowWatchers();
12802
+ this.initializeGroupWatchers();
12803
+
12514
12804
  this.subscribe("column-init", this.initializeColumn.bind(this));
12515
- this.subscribe("row-init", this.initializeRow.bind(this));
12516
12805
  }
12517
-
12518
- layoutCell(cell){
12519
- if(cell.column.definition.contextMenu || cell.column.definition.clickMenu){
12520
- this.initializeCell(cell);
12806
+
12807
+ lookupMenuContainer(){
12808
+
12809
+ this.menuContainer = this.table.options.menuContainer;
12810
+
12811
+ if(typeof this.menuContainer === "string"){
12812
+ this.menuContainer = document.querySelector(this.menuContainer);
12813
+
12814
+ if(!this.menuContainer){
12815
+ console.warn("Menu Error - no container element found matching selector:", this.table.options.menuContainer , "(defaulting to document body)");
12816
+ }
12817
+ }else if (this.menuContainer === true){
12818
+ this.menuContainer = this.table.element;
12819
+ }
12820
+
12821
+ if(this.menuContainer && !this.checkMenuContainerIsParent(this.menuContainer)){
12822
+ this.menuContainer = false;
12823
+ console.warn("Menu Error - container element does not contain this table:", this.table.options.menuContainer , "(defaulting to document body)");
12824
+ }
12825
+
12826
+ if(!this.menuContainer){
12827
+ this.menuContainer = document.body;
12828
+ }
12829
+ }
12830
+
12831
+ checkMenuContainerIsParent(container, element = this.table.element){
12832
+ if(container === element){
12833
+ return true;
12834
+ }else {
12835
+ return element.parentNode ? this.checkMenuContainerIsParent(container, element.parentNode) : false;
12521
12836
  }
12522
12837
  }
12523
-
12524
- initializeColumn(column){
12525
- var def = column.definition;
12526
-
12527
- if(def.headerContextMenu || def.headerClickMenu || def.headerMenu){
12528
- this.initializeColumnHeader(column);
12838
+
12839
+ initializeRowWatchers(){
12840
+ if(this.table.options.rowContextMenu){
12841
+ this.subscribe("row-contextmenu", this.loadMenuEvent.bind(this, this.table.options.rowContextMenu));
12842
+ this.table.on("rowTapHold", this.loadMenuEvent.bind(this, this.table.options.rowContextMenu));
12843
+ }
12844
+
12845
+ if(this.table.options.rowClickMenu){
12846
+ this.subscribe("row-click", this.loadMenuEvent.bind(this, this.table.options.rowClickMenu));
12529
12847
  }
12530
12848
  }
12531
-
12532
- initializeColumnHeader(column){
12533
- var headerMenuEl;
12534
-
12535
- if(column.definition.headerContextMenu){
12536
- column.getElement().addEventListener("contextmenu", this.LoadMenuEvent.bind(this, column, column.definition.headerContextMenu));
12537
- this.tapHold(column, column.definition.headerContextMenu);
12849
+
12850
+ initializeGroupWatchers(){
12851
+ if(this.table.options.groupContextMenu){
12852
+ this.subscribe("group-contextmenu", this.loadMenuEvent.bind(this, this.table.options.groupContextMenu));
12853
+ this.table.on("groupTapHold", this.loadMenuEvent.bind(this, this.table.options.groupContextMenu));
12538
12854
  }
12539
-
12540
- // if(column.definition.headerClickMenu){
12541
- // column.getElement().addEventListener("click", this.LoadMenuEvent.bind(this, column, column.definition.headerClickMenu));
12542
- // }
12543
-
12544
- if(column.definition.headerMenu){
12545
-
12546
- headerMenuEl = document.createElement("span");
12547
- headerMenuEl.classList.add("tabulator-header-menu-button");
12548
- headerMenuEl.innerHTML = "&vellip;";
12549
-
12550
- headerMenuEl.addEventListener("click", (e) => {
12551
- e.stopPropagation();
12552
- e.preventDefault();
12553
-
12554
- this.LoadMenuEvent(column, column.definition.headerMenu, e);
12555
- });
12556
-
12557
- column.titleElement.insertBefore(headerMenuEl, column.titleElement.firstChild);
12855
+
12856
+ if(this.table.options.groupClickMenu){
12857
+ this.subscribe("group-click", this.loadMenuEvent.bind(this, this.table.options.groupClickMenu));
12558
12858
  }
12559
12859
  }
12560
-
12561
- LoadMenuEvent(component, menu, e){
12562
- menu = typeof menu == "function" ? menu.call(this.table, component.getComponent(), e) : menu;
12563
-
12564
- // if(component instanceof Cell){
12565
- // e.stopImmediatePropagation();
12566
- // }
12567
-
12568
- this.loadMenu(e, component, menu);
12569
- }
12570
-
12571
- tapHold(component, menu){
12572
- var element = component.getElement(),
12573
- tapHold = null,
12574
- loaded = false;
12575
-
12576
- element.addEventListener("touchstart", (e) => {
12577
- clearTimeout(tapHold);
12578
- loaded = false;
12579
-
12580
- tapHold = setTimeout(() => {
12581
- clearTimeout(tapHold);
12582
- tapHold = null;
12583
- loaded = true;
12584
-
12585
- this.LoadMenuEvent(component, menu, e);
12586
- }, 1000);
12587
-
12588
- }, {passive: true});
12589
-
12590
- element.addEventListener("touchend", (e) => {
12591
- clearTimeout(tapHold);
12592
- tapHold = null;
12593
-
12594
- if(loaded){
12595
- e.preventDefault();
12596
- }
12860
+
12861
+ initializeColumn(column){
12862
+ var def = column.definition;
12863
+
12864
+ //handle column events
12865
+ if(def.headerContextMenu && !this.columnSubscribers.headerContextMenu){
12866
+ this.columnSubscribers.headerContextMenu = this.loadMenuTableColumnEvent.bind(this, "headerContextMenu");
12867
+ this.subscribe("column-contextmenu", this.columnSubscribers.headerContextMenu);
12868
+ this.table.on("headerTapHold", this.loadMenuTableColumnEvent.bind(this, "headerContextMenu"));
12869
+ }
12870
+
12871
+ if(def.headerClickMenu && !this.columnSubscribers.headerClickMenu){
12872
+ this.columnSubscribers.headerClickMenu = this.loadMenuTableColumnEvent.bind(this, "headerClickMenu");
12873
+ this.subscribe("column-click", this.columnSubscribers.headerClickMenu);
12874
+ }
12875
+
12876
+ if(def.headerMenu){
12877
+ this.initializeColumnHeaderMenu(column);
12878
+ }
12879
+
12880
+ //handle cell events
12881
+ if(def.contextMenu && !this.columnSubscribers.contextMenu){
12882
+ this.columnSubscribers.contextMenu = this.loadMenuTableCellEvent.bind(this, "contextMenu");
12883
+ this.subscribe("cell-contextmenu", this.columnSubscribers.contextMenu);
12884
+ this.table.on("cellTapHold", this.loadMenuTableCellEvent.bind(this, "contextMenu"));
12885
+ }
12886
+
12887
+ if(def.clickMenu && !this.columnSubscribers.clickMenu){
12888
+ this.columnSubscribers.clickMenu = this.loadMenuTableCellEvent.bind(this, "clickMenu");
12889
+ this.subscribe("cell-click", this.columnSubscribers.clickMenu);
12890
+ }
12891
+ }
12892
+
12893
+ initializeColumnHeaderMenu(column){
12894
+ var headerMenuEl;
12895
+
12896
+ headerMenuEl = document.createElement("span");
12897
+ headerMenuEl.classList.add("tabulator-header-menu-button");
12898
+ headerMenuEl.innerHTML = "&vellip;";
12899
+
12900
+ headerMenuEl.addEventListener("click", (e) => {
12901
+ e.stopPropagation();
12902
+ e.preventDefault();
12903
+
12904
+ this.loadMenuEvent(column.definition.headerMenu, e, column);
12597
12905
  });
12906
+
12907
+ column.titleElement.insertBefore(headerMenuEl, column.titleElement.firstChild);
12598
12908
  }
12599
-
12600
- initializeCell(cell){
12601
- if(cell.column.definition.contextMenu){
12602
- cell.getElement(true).addEventListener("contextmenu", this.LoadMenuEvent.bind(this, cell, cell.column.definition.contextMenu));
12603
- this.tapHold(cell, cell.column.definition.contextMenu);
12909
+
12910
+ loadMenuTableCellEvent(option, e, cell){
12911
+ if(cell._cell){
12912
+ cell = cell._cell;
12604
12913
  }
12605
-
12606
- if(cell.column.definition.clickMenu){
12607
- cell.getElement(true).addEventListener("click", this.LoadMenuEvent.bind(this, cell, cell.column.definition.clickMenu));
12914
+
12915
+ if(cell.column.definition[option]){
12916
+ this.loadMenuEvent(cell.column.definition[option], e, cell);
12608
12917
  }
12609
12918
  }
12610
-
12611
- initializeRow(row){
12612
- if(this.table.options.rowContextMenu){
12613
- row.getElement().addEventListener("contextmenu", this.LoadMenuEvent.bind(this, row, this.table.options.rowContextMenu));
12614
- this.tapHold(row, this.table.options.rowContextMenu);
12919
+
12920
+ loadMenuTableColumnEvent(option, e, column){
12921
+ if(column._column){
12922
+ column = column._column;
12615
12923
  }
12616
-
12617
- if(this.table.options.rowClickMenu){
12618
- row.getElement().addEventListener("click", this.LoadMenuEvent.bind(this, row, this.table.options.rowClickMenu));
12924
+
12925
+ if(column.definition[option]){
12926
+ this.loadMenuEvent(column.definition[option], e, column);
12619
12927
  }
12620
12928
  }
12621
-
12622
- initializeGroup (group){
12623
- if(this.table.options.groupContextMenu){
12624
- group.getElement().addEventListener("contextmenu", this.LoadMenuEvent.bind(this, group, this.table.options.groupContextMenu));
12625
- this.tapHold(group, this.table.options.groupContextMenu);
12626
- }
12627
-
12628
- if(this.table.options.groupClickMenu){
12629
- group.getElement().addEventListener("click", this.LoadMenuEvent.bind(this, group, this.table.options.groupClickMenu));
12929
+
12930
+ loadMenuEvent(menu, e, component){
12931
+ if(component._group){
12932
+ component = component._group;
12933
+ }else if(component._row){
12934
+ component = component._row;
12630
12935
  }
12936
+
12937
+ menu = typeof menu == "function" ? menu.call(this.table, component.getComponent(), e) : menu;
12938
+
12939
+ this.loadMenu(e, component, menu);
12631
12940
  }
12632
-
12941
+
12633
12942
  loadMenu(e, component, menu, parentEl){
12634
-
12635
12943
  var touch = !(e instanceof MouseEvent);
12636
-
12944
+
12637
12945
  var menuEl = document.createElement("div");
12638
12946
  menuEl.classList.add("tabulator-menu");
12639
-
12947
+
12640
12948
  if(!touch){
12641
12949
  e.preventDefault();
12642
12950
  }
12643
-
12951
+
12644
12952
  //abort if no menu set
12645
12953
  if(!menu || !menu.length){
12646
12954
  return;
12647
12955
  }
12648
-
12956
+
12649
12957
  if(!parentEl){
12650
12958
  if(this.nestedMenuBlock){
12651
12959
  //abort if child menu already open
@@ -12657,35 +12965,35 @@ class Menu extends Module{
12657
12965
  this.nestedMenuBlock = false;
12658
12966
  }, 100);
12659
12967
  }
12660
-
12968
+
12661
12969
  this.hideMenu();
12662
12970
  this.menuElements = [];
12663
12971
  }
12664
-
12972
+
12665
12973
  menu.forEach((item) => {
12666
12974
  var itemEl = document.createElement("div"),
12667
12975
  label = item.label,
12668
12976
  disabled = item.disabled;
12669
-
12977
+
12670
12978
  if(item.separator){
12671
12979
  itemEl.classList.add("tabulator-menu-separator");
12672
12980
  }else {
12673
12981
  itemEl.classList.add("tabulator-menu-item");
12674
-
12982
+
12675
12983
  if(typeof label == "function"){
12676
12984
  label = label.call(this.table, component.getComponent());
12677
12985
  }
12678
-
12986
+
12679
12987
  if(label instanceof Node){
12680
12988
  itemEl.appendChild(label);
12681
12989
  }else {
12682
12990
  itemEl.innerHTML = label;
12683
12991
  }
12684
-
12992
+
12685
12993
  if(typeof disabled == "function"){
12686
12994
  disabled = disabled.call(this.table, component.getComponent());
12687
12995
  }
12688
-
12996
+
12689
12997
  if(disabled){
12690
12998
  itemEl.classList.add("tabulator-menu-item-disabled");
12691
12999
  itemEl.addEventListener("click", (e) => {
@@ -12706,57 +13014,67 @@ class Menu extends Module{
12706
13014
  }
12707
13015
  }
12708
13016
  }
12709
-
13017
+
12710
13018
  if(item.menu && item.menu.length){
12711
13019
  itemEl.classList.add("tabulator-menu-item-submenu");
12712
13020
  }
12713
13021
  }
12714
-
13022
+
12715
13023
  menuEl.appendChild(itemEl);
12716
13024
  });
12717
-
13025
+
12718
13026
  menuEl.addEventListener("click", (e) => {
12719
13027
  this.hideMenu();
12720
13028
  });
12721
-
13029
+
12722
13030
  this.menuElements.push(menuEl);
12723
13031
  this.positionMenu(menuEl, parentEl, touch, e);
13032
+
13033
+ this.currentComponent = component;
13034
+
13035
+ this.dispatchExternal("menuOpened", component.getComponent());
12724
13036
  }
12725
-
13037
+
12726
13038
  hideOldSubMenus(menuEl){
12727
13039
  var index = this.menuElements.indexOf(menuEl);
12728
-
13040
+
12729
13041
  if(index > -1){
12730
13042
  for(let i = this.menuElements.length - 1; i > index; i--){
12731
13043
  var el = this.menuElements[i];
12732
-
13044
+
12733
13045
  if(el.parentNode){
12734
13046
  el.parentNode.removeChild(el);
12735
13047
  }
12736
-
13048
+
12737
13049
  this.menuElements.pop();
12738
13050
  }
12739
13051
  }
12740
13052
  }
12741
-
13053
+
12742
13054
  positionMenu(element, parentEl, touch, e){
12743
- var docHeight = Math.max(document.body.offsetHeight, window.innerHeight),
12744
- x, y, parentOffset;
12745
-
13055
+ var x, y, parentOffset;
13056
+
12746
13057
  if(!parentEl){
12747
13058
  x = touch ? e.touches[0].pageX : e.pageX;
12748
13059
  y = touch ? e.touches[0].pageY : e.pageY;
12749
-
13060
+
13061
+ if(this.menuContainer !== document.body){
13062
+ parentOffset = Helpers.elOffset(this.menuContainer);
13063
+
13064
+ x -= parentOffset.left;
13065
+ y -= parentOffset.top;
13066
+ }
13067
+
12750
13068
  this.positionReversedX = false;
12751
13069
  }else {
12752
13070
  parentOffset = Helpers.elOffset(parentEl);
12753
13071
  x = parentOffset.left + parentEl.offsetWidth;
12754
13072
  y = parentOffset.top - 1;
12755
13073
  }
12756
-
13074
+
12757
13075
  element.style.top = y + "px";
12758
13076
  element.style.left = x + "px";
12759
-
13077
+
12760
13078
  setTimeout(() => {
12761
13079
  this.table.rowManager.element.addEventListener("scroll", this.blurEvent);
12762
13080
  document.body.addEventListener("click", this.blurEvent);
@@ -12764,66 +13082,71 @@ class Menu extends Module{
12764
13082
  window.addEventListener("resize", this.blurEvent);
12765
13083
  document.body.addEventListener("keydown", this.escEvent);
12766
13084
  }, 100);
12767
-
12768
- document.body.appendChild(element);
12769
-
12770
- //move menu to start on bottom edge if it is too close to the edge of the screen
12771
- if((y + element.offsetHeight) >= docHeight){
12772
- element.style.top = "";
12773
-
13085
+
13086
+ this.menuContainer.appendChild(element);
13087
+
13088
+ //move menu to start on right edge if it is too close to the edge of the screen
13089
+ if((x + element.offsetWidth) >= this.menuContainer.offsetWidth || this.positionReversedX){
13090
+ element.style.left = "";
13091
+
12774
13092
  if(parentEl){
12775
- element.style.bottom = (docHeight - parentOffset.top - parentEl.offsetHeight - 1) + "px";
13093
+ element.style.right = (this.menuContainer.offsetWidth - parentOffset.left) + "px";
12776
13094
  }else {
12777
- element.style.bottom = (docHeight - y) + "px";
13095
+ element.style.right = (this.menuContainer.offsetWidth - x) + "px";
12778
13096
  }
13097
+
13098
+ this.positionReversedX = true;
12779
13099
  }
12780
-
12781
- //move menu to start on right edge if it is too close to the edge of the screen
12782
- if((x + element.offsetWidth) >= document.body.offsetWidth || this.positionReversedX){
12783
- element.style.left = "";
12784
-
13100
+
13101
+ //move menu to start on bottom edge if it is too close to the edge of the screen
13102
+ if((y + element.offsetHeight) >= this.menuContainer.offsetHeight){
13103
+ element.style.top = "";
13104
+
12785
13105
  if(parentEl){
12786
- element.style.right = (document.documentElement.offsetWidth - parentOffset.left) + "px";
13106
+ element.style.bottom = (this.menuContainer.offsetHeight - parentOffset.top - parentEl.offsetHeight - 1) + "px";
12787
13107
  }else {
12788
- element.style.right = (document.documentElement.offsetWidth - x) + "px";
13108
+ element.style.bottom = (this.menuContainer.offsetHeight - y) + "px";
12789
13109
  }
12790
-
12791
- this.positionReversedX = true;
12792
13110
  }
12793
13111
  }
12794
-
13112
+
12795
13113
  isOpen(){
12796
13114
  return !!this.menuElements.length;
12797
13115
  }
12798
-
13116
+
12799
13117
  escMenu(e){
12800
13118
  if(e.keyCode == 27){
12801
13119
  this.hideMenu();
12802
13120
  }
12803
13121
  }
12804
-
12805
- hideMenu(){
13122
+
13123
+ hideMenu(){
12806
13124
  this.menuElements.forEach((menuEl) => {
12807
13125
  if(menuEl.parentNode){
12808
13126
  menuEl.parentNode.removeChild(menuEl);
12809
13127
  }
12810
13128
  });
12811
-
13129
+
12812
13130
  document.body.removeEventListener("keydown", this.escEvent);
12813
13131
  document.body.removeEventListener("click", this.blurEvent);
12814
13132
  document.body.removeEventListener("contextmenu", this.blurEvent);
12815
13133
  window.removeEventListener("resize", this.blurEvent);
12816
13134
  this.table.rowManager.element.removeEventListener("scroll", this.blurEvent);
13135
+
13136
+ if(this.currentComponent){
13137
+ this.dispatchExternal("menuClosed", this.currentComponent.getComponent());
13138
+ this.currentComponent = null;
13139
+ }
12817
13140
  }
12818
13141
  }
12819
13142
 
12820
13143
  Menu.moduleName = "menu";
12821
13144
 
12822
13145
  class MoveColumns extends Module{
12823
-
13146
+
12824
13147
  constructor(table){
12825
13148
  super(table);
12826
-
13149
+
12827
13150
  this.placeholderElement = this.createPlaceholderElement();
12828
13151
  this.hoverElement = false; //floating column header element
12829
13152
  this.checkTimeout = false; //click check timeout holder
@@ -12836,35 +13159,36 @@ class MoveColumns extends Module{
12836
13159
  this.autoScrollStep = 5; //auto scroll distance in pixels
12837
13160
  this.autoScrollTimeout = false; //auto scroll timeout
12838
13161
  this.touchMove = false;
12839
-
13162
+
12840
13163
  this.moveHover = this.moveHover.bind(this);
12841
13164
  this.endMove = this.endMove.bind(this);
12842
-
13165
+
12843
13166
  this.registerTableOption("movableColumns", false); //enable movable columns
12844
13167
  }
12845
-
13168
+
12846
13169
  createPlaceholderElement(){
12847
13170
  var el = document.createElement("div");
12848
-
13171
+
12849
13172
  el.classList.add("tabulator-col");
12850
13173
  el.classList.add("tabulator-col-placeholder");
12851
-
13174
+
12852
13175
  return el;
12853
13176
  }
12854
-
13177
+
12855
13178
  initialize(){
12856
- this.subscribe("column-init", this.initializeColumn.bind(this));
13179
+ if(this.table.options.movableColumns){
13180
+ this.subscribe("column-init", this.initializeColumn.bind(this));
13181
+ }
12857
13182
  }
12858
-
13183
+
12859
13184
  initializeColumn(column){
12860
13185
  var self = this,
12861
13186
  config = {},
12862
13187
  colEl;
12863
-
13188
+
12864
13189
  if(!column.modules.frozen){
12865
-
12866
13190
  colEl = column.getElement();
12867
-
13191
+
12868
13192
  config.mousemove = function(e){
12869
13193
  if(column.parent === self.moving.parent){
12870
13194
  if((((self.touchMove ? e.touches[0].pageX : e.pageX) - Helpers.elOffset(colEl).left) + self.table.columnManager.element.scrollLeft) > (column.getWidth() / 2)){
@@ -12880,7 +13204,7 @@ class MoveColumns extends Module{
12880
13204
  }
12881
13205
  }
12882
13206
  }.bind(self);
12883
-
13207
+
12884
13208
  colEl.addEventListener("mousedown", function(e){
12885
13209
  self.touchMove = false;
12886
13210
  if(e.which === 1){
@@ -12889,7 +13213,7 @@ class MoveColumns extends Module{
12889
13213
  }, self.checkPeriod);
12890
13214
  }
12891
13215
  });
12892
-
13216
+
12893
13217
  colEl.addEventListener("mouseup", function(e){
12894
13218
  if(e.which === 1){
12895
13219
  if(self.checkTimeout){
@@ -12897,18 +13221,18 @@ class MoveColumns extends Module{
12897
13221
  }
12898
13222
  }
12899
13223
  });
12900
-
13224
+
12901
13225
  self.bindTouchEvents(column);
12902
13226
  }
12903
-
13227
+
12904
13228
  column.modules.moveColumn = config;
12905
13229
  }
12906
-
13230
+
12907
13231
  bindTouchEvents(column){
12908
13232
  var colEl = column.getElement(),
12909
13233
  startXMove = false, //shifting center position of the cell
12910
13234
  nextCol, prevCol, nextColWidth, prevColWidth, nextColWidthLast, prevColWidthLast;
12911
-
13235
+
12912
13236
  colEl.addEventListener("touchstart", (e) => {
12913
13237
  this.checkTimeout = setTimeout(() => {
12914
13238
  this.touchMove = true;
@@ -12919,27 +13243,27 @@ class MoveColumns extends Module{
12919
13243
  nextColWidthLast = 0;
12920
13244
  prevColWidthLast = 0;
12921
13245
  startXMove = false;
12922
-
13246
+
12923
13247
  this.startMove(e, column);
12924
13248
  }, this.checkPeriod);
12925
13249
  }, {passive: true});
12926
-
13250
+
12927
13251
  colEl.addEventListener("touchmove", (e) => {
12928
13252
  var diff, moveToCol;
12929
-
13253
+
12930
13254
  if(this.moving){
12931
13255
  this.moveHover(e);
12932
-
13256
+
12933
13257
  if(!startXMove){
12934
13258
  startXMove = e.touches[0].pageX;
12935
13259
  }
12936
-
13260
+
12937
13261
  diff = e.touches[0].pageX - startXMove;
12938
-
13262
+
12939
13263
  if(diff > 0){
12940
13264
  if(nextCol && diff - nextColWidthLast > nextColWidth){
12941
13265
  moveToCol = nextCol;
12942
-
13266
+
12943
13267
  if(moveToCol !== column){
12944
13268
  startXMove = e.touches[0].pageX;
12945
13269
  moveToCol.getElement().parentNode.insertBefore(this.placeholderElement, moveToCol.getElement().nextSibling);
@@ -12949,7 +13273,7 @@ class MoveColumns extends Module{
12949
13273
  }else {
12950
13274
  if(prevCol && -diff - prevColWidthLast > prevColWidth){
12951
13275
  moveToCol = prevCol;
12952
-
13276
+
12953
13277
  if(moveToCol !== column){
12954
13278
  startXMove = e.touches[0].pageX;
12955
13279
  moveToCol.getElement().parentNode.insertBefore(this.placeholderElement, moveToCol.getElement());
@@ -12957,7 +13281,7 @@ class MoveColumns extends Module{
12957
13281
  }
12958
13282
  }
12959
13283
  }
12960
-
13284
+
12961
13285
  if(moveToCol){
12962
13286
  nextCol = moveToCol.nextColumn();
12963
13287
  nextColWidthLast = nextColWidth;
@@ -12968,7 +13292,7 @@ class MoveColumns extends Module{
12968
13292
  }
12969
13293
  }
12970
13294
  }, {passive: true});
12971
-
13295
+
12972
13296
  colEl.addEventListener("touchend", (e) => {
12973
13297
  if(this.checkTimeout){
12974
13298
  clearTimeout(this.checkTimeout);
@@ -12978,43 +13302,43 @@ class MoveColumns extends Module{
12978
13302
  }
12979
13303
  });
12980
13304
  }
12981
-
13305
+
12982
13306
  startMove(e, column){
12983
13307
  var element = column.getElement(),
12984
13308
  headerElement = this.table.columnManager.getElement(),
12985
13309
  headersElement = this.table.columnManager.getHeadersElement();
12986
-
13310
+
12987
13311
  this.moving = column;
12988
13312
  this.startX = (this.touchMove ? e.touches[0].pageX : e.pageX) - Helpers.elOffset(element).left;
12989
-
13313
+
12990
13314
  this.table.element.classList.add("tabulator-block-select");
12991
-
13315
+
12992
13316
  //create placeholder
12993
13317
  this.placeholderElement.style.width = column.getWidth() + "px";
12994
13318
  this.placeholderElement.style.height = column.getHeight() + "px";
12995
-
13319
+
12996
13320
  element.parentNode.insertBefore(this.placeholderElement, element);
12997
13321
  element.parentNode.removeChild(element);
12998
-
13322
+
12999
13323
  //create hover element
13000
13324
  this.hoverElement = element.cloneNode(true);
13001
13325
  this.hoverElement.classList.add("tabulator-moving");
13002
-
13326
+
13003
13327
  this.table.columnManager.getElement().appendChild(this.hoverElement);
13004
-
13328
+
13005
13329
  this.hoverElement.style.left = "0";
13006
13330
  this.hoverElement.style.bottom = (headerElement.clientHeight - headersElement.offsetHeight) + "px";
13007
-
13331
+
13008
13332
  if(!this.touchMove){
13009
13333
  this._bindMouseMove();
13010
-
13334
+
13011
13335
  document.body.addEventListener("mousemove", this.moveHover);
13012
13336
  document.body.addEventListener("mouseup", this.endMove);
13013
13337
  }
13014
-
13338
+
13015
13339
  this.moveHover(e);
13016
13340
  }
13017
-
13341
+
13018
13342
  _bindMouseMove(){
13019
13343
  this.table.columnManager.columnsByIndex.forEach(function(column){
13020
13344
  if(column.modules.moveColumn.mousemove){
@@ -13022,7 +13346,7 @@ class MoveColumns extends Module{
13022
13346
  }
13023
13347
  });
13024
13348
  }
13025
-
13349
+
13026
13350
  _unbindMouseMove(){
13027
13351
  this.table.columnManager.columnsByIndex.forEach(function(column){
13028
13352
  if(column.modules.moveColumn.mousemove){
@@ -13030,17 +13354,17 @@ class MoveColumns extends Module{
13030
13354
  }
13031
13355
  });
13032
13356
  }
13033
-
13357
+
13034
13358
  moveColumn(column, after){
13035
13359
  var movingCells = this.moving.getCells();
13036
-
13360
+
13037
13361
  this.toCol = column;
13038
13362
  this.toColAfter = after;
13039
-
13363
+
13040
13364
  if(after){
13041
13365
  column.getCells().forEach(function(cell, i){
13042
13366
  var cellEl = cell.getElement(true);
13043
-
13367
+
13044
13368
  if(cellEl.parentNode && movingCells[i]){
13045
13369
  cellEl.parentNode.insertBefore(movingCells[i].getElement(), cellEl.nextSibling);
13046
13370
  }
@@ -13048,47 +13372,47 @@ class MoveColumns extends Module{
13048
13372
  }else {
13049
13373
  column.getCells().forEach(function(cell, i){
13050
13374
  var cellEl = cell.getElement(true);
13051
-
13375
+
13052
13376
  if(cellEl.parentNode && movingCells[i]){
13053
13377
  cellEl.parentNode.insertBefore(movingCells[i].getElement(), cellEl);
13054
13378
  }
13055
13379
  });
13056
13380
  }
13057
13381
  }
13058
-
13382
+
13059
13383
  endMove(e){
13060
13384
  if(e.which === 1 || this.touchMove){
13061
13385
  this._unbindMouseMove();
13062
-
13386
+
13063
13387
  this.placeholderElement.parentNode.insertBefore(this.moving.getElement(), this.placeholderElement.nextSibling);
13064
13388
  this.placeholderElement.parentNode.removeChild(this.placeholderElement);
13065
13389
  this.hoverElement.parentNode.removeChild(this.hoverElement);
13066
-
13390
+
13067
13391
  this.table.element.classList.remove("tabulator-block-select");
13068
-
13392
+
13069
13393
  if(this.toCol){
13070
13394
  this.table.columnManager.moveColumnActual(this.moving, this.toCol, this.toColAfter);
13071
13395
  }
13072
-
13396
+
13073
13397
  this.moving = false;
13074
13398
  this.toCol = false;
13075
13399
  this.toColAfter = false;
13076
-
13400
+
13077
13401
  if(!this.touchMove){
13078
13402
  document.body.removeEventListener("mousemove", this.moveHover);
13079
13403
  document.body.removeEventListener("mouseup", this.endMove);
13080
13404
  }
13081
13405
  }
13082
13406
  }
13083
-
13407
+
13084
13408
  moveHover(e){
13085
13409
  var columnHolder = this.table.columnManager.getElement(),
13086
13410
  scrollLeft = columnHolder.scrollLeft,
13087
13411
  xPos = ((this.touchMove ? e.touches[0].pageX : e.pageX) - Helpers.elOffset(columnHolder).left) + scrollLeft,
13088
13412
  scrollPos;
13089
-
13413
+
13090
13414
  this.hoverElement.style.left = (xPos - this.startX) + "px";
13091
-
13415
+
13092
13416
  if(xPos - scrollLeft < this.autoScrollMargin){
13093
13417
  if(!this.autoScrollTimeout){
13094
13418
  this.autoScrollTimeout = setTimeout(() => {
@@ -13098,7 +13422,7 @@ class MoveColumns extends Module{
13098
13422
  }, 1);
13099
13423
  }
13100
13424
  }
13101
-
13425
+
13102
13426
  if(scrollLeft + columnHolder.clientWidth - xPos < this.autoScrollMargin){
13103
13427
  if(!this.autoScrollTimeout){
13104
13428
  this.autoScrollTimeout = setTimeout(() => {
@@ -13430,6 +13754,8 @@ class MoveRows extends Module{
13430
13754
  document.body.addEventListener("mousemove", this.moveHover);
13431
13755
  document.body.addEventListener("mouseup", this.endMove);
13432
13756
 
13757
+ this.dispatchExternal("rowMoving", row.getComponent());
13758
+
13433
13759
  this.moveHover(e);
13434
13760
  }
13435
13761
 
@@ -13464,6 +13790,8 @@ class MoveRows extends Module{
13464
13790
 
13465
13791
  if(this.toRow){
13466
13792
  this.table.rowManager.moveRow(this.moving, this.toRow, this.toRowAfter);
13793
+ }else {
13794
+ this.dispatchExternal("rowMoveCancelled", this.moving.getComponent());
13467
13795
  }
13468
13796
 
13469
13797
  this.moving = false;
@@ -13878,44 +14206,121 @@ Mutator.moduleName = "mutator";
13878
14206
  //load defaults
13879
14207
  Mutator.mutators = defaultMutators;
13880
14208
 
14209
+ function rows(pageSize, currentRow, currentPage, totalRows, totalPages){
14210
+ var el = document.createElement("span"),
14211
+ showingEl = document.createElement("span"),
14212
+ valueEl = document.createElement("span"),
14213
+ ofEl = document.createElement("span"),
14214
+ totalEl = document.createElement("span"),
14215
+ rowsEl = document.createElement("span");
14216
+
14217
+ this.table.modules.localize.langBind("pagination|counter|showing", (value) => {
14218
+ showingEl.innerHTML = value;
14219
+ });
14220
+
14221
+ valueEl.innerHTML = " " + currentRow + "-" + Math.min((currentRow + pageSize - 1), totalRows) + " ";
14222
+
14223
+ this.table.modules.localize.langBind("pagination|counter|of", (value) => {
14224
+ ofEl.innerHTML = value;
14225
+ });
14226
+
14227
+ totalEl.innerHTML = " " + totalRows + " ";
14228
+
14229
+ this.table.modules.localize.langBind("pagination|counter|rows", (value) => {
14230
+ rowsEl.innerHTML = value;
14231
+ });
14232
+
14233
+ el.appendChild(showingEl);
14234
+ el.appendChild(valueEl);
14235
+ el.appendChild(ofEl);
14236
+ el.appendChild(totalEl);
14237
+ el.appendChild(rowsEl);
14238
+
14239
+ return el;
14240
+ }
14241
+
14242
+ function pages(pageSize, currentRow, currentPage, totalRows, totalPages){
14243
+
14244
+ var el = document.createElement("span"),
14245
+ showingEl = document.createElement("span"),
14246
+ valueEl = document.createElement("span"),
14247
+ ofEl = document.createElement("span"),
14248
+ totalEl = document.createElement("span"),
14249
+ rowsEl = document.createElement("span");
14250
+
14251
+ this.table.modules.localize.langBind("pagination|counter|showing", (value) => {
14252
+ showingEl.innerHTML = value;
14253
+ });
14254
+
14255
+ valueEl.innerHTML = " " + currentPage + " ";
14256
+
14257
+ this.table.modules.localize.langBind("pagination|counter|of", (value) => {
14258
+ ofEl.innerHTML = value;
14259
+ });
14260
+
14261
+ totalEl.innerHTML = " " + totalPages + " ";
14262
+
14263
+ this.table.modules.localize.langBind("pagination|counter|pages", (value) => {
14264
+ rowsEl.innerHTML = value;
14265
+ });
14266
+
14267
+ el.appendChild(showingEl);
14268
+ el.appendChild(valueEl);
14269
+ el.appendChild(ofEl);
14270
+ el.appendChild(totalEl);
14271
+ el.appendChild(rowsEl);
14272
+
14273
+ return el;
14274
+ }
14275
+
14276
+ var defaultPageCounters = {
14277
+ rows:rows,
14278
+ pages:pages,
14279
+ };
14280
+
13881
14281
  class Page extends Module{
13882
-
14282
+
13883
14283
  constructor(table){
13884
14284
  super(table);
13885
-
14285
+
13886
14286
  this.mode = "local";
13887
14287
  this.progressiveLoad = false;
13888
-
14288
+
14289
+ this.element = null;
14290
+ this.pageCounterElement = null;
14291
+ this.pageCounter = null;
14292
+
13889
14293
  this.size = 0;
13890
14294
  this.page = 1;
13891
14295
  this.count = 5;
13892
14296
  this.max = 1;
13893
14297
 
14298
+ this.remoteRowCountEstimate = null;
14299
+
13894
14300
  this.displayIndex = 0; //index in display pipeline
13895
-
14301
+
13896
14302
  this.initialLoad = true;
13897
14303
  this.dataChanging = false; //flag to check if data is being changed by this module
13898
-
14304
+
13899
14305
  this.pageSizes = [];
13900
-
13901
- this.dataReceivedNames = {}; //TODO - remove once pagimation update is complete
13902
- this.dataSentNames = {}; //TODO - remove once pagimation update is complete
13903
-
14306
+
13904
14307
  this.registerTableOption("pagination", false); //set pagination type
13905
14308
  this.registerTableOption("paginationMode", "local"); //local or remote pagination
13906
14309
  this.registerTableOption("paginationSize", false); //set number of rows to a page
13907
- this.registerTableOption("paginationInitialPage", 1); //initail page to show on load
14310
+ this.registerTableOption("paginationInitialPage", 1); //initial page to show on load
14311
+ this.registerTableOption("paginationCounter", false); // set pagination counter
14312
+ this.registerTableOption("paginationCounterElement", false); // set pagination counter
13908
14313
  this.registerTableOption("paginationButtonCount", 5); // set count of page button
13909
14314
  this.registerTableOption("paginationSizeSelector", false); //add pagination size selector element
13910
14315
  this.registerTableOption("paginationElement", false); //element to hold pagination numbers
13911
14316
  // this.registerTableOption("paginationDataSent", {}); //pagination data sent to the server
13912
14317
  // this.registerTableOption("paginationDataReceived", {}); //pagination data received from the server
13913
14318
  this.registerTableOption("paginationAddRow", "page"); //add rows on table or page
13914
-
14319
+
13915
14320
  this.registerTableOption("progressiveLoad", false); //progressive loading
13916
14321
  this.registerTableOption("progressiveLoadDelay", 0); //delay between requests
13917
14322
  this.registerTableOption("progressiveLoadScrollMargin", 0); //margin before scroll begins
13918
-
14323
+
13919
14324
  this.registerTableFunction("setMaxPage", this.setMaxPage.bind(this));
13920
14325
  this.registerTableFunction("setPage", this.setPage.bind(this));
13921
14326
  this.registerTableFunction("setPageToRow", this.userSetPageToRow.bind(this));
@@ -13925,11 +14330,11 @@ class Page extends Module{
13925
14330
  this.registerTableFunction("nextPage", this.nextPage.bind(this));
13926
14331
  this.registerTableFunction("getPage", this.getPage.bind(this));
13927
14332
  this.registerTableFunction("getPageMax", this.getPageMax.bind(this));
13928
-
14333
+
13929
14334
  //register component functions
13930
14335
  this.registerComponentFunction("row", "pageTo", this.setPageToRow.bind(this));
13931
14336
  }
13932
-
14337
+
13933
14338
  initialize(){
13934
14339
  if(this.table.options.pagination){
13935
14340
  this.subscribe("row-deleted", this.rowsUpdated.bind(this));
@@ -13937,40 +14342,41 @@ class Page extends Module{
13937
14342
  this.subscribe("row-added", this.rowsUpdated.bind(this));
13938
14343
  this.subscribe("data-processed", this.initialLoadComplete.bind(this));
13939
14344
  this.subscribe("table-built", this.calculatePageSizes.bind(this));
13940
-
14345
+
13941
14346
  if(this.table.options.paginationMode === "remote"){
13942
14347
  this.subscribe("data-params", this.remotePageParams.bind(this));
13943
14348
  this.subscribe("data-loaded", this._parseRemoteData.bind(this));
13944
14349
  }
13945
-
14350
+
13946
14351
  if(this.table.options.progressiveLoad){
13947
14352
  console.error("Progressive Load Error - Pagination and progressive load cannot be used at the same time");
13948
14353
  }
13949
-
14354
+
13950
14355
  this.registerDisplayHandler(this.restOnRenderBefore.bind(this), 40);
13951
14356
  this.registerDisplayHandler(this.getRows.bind(this), 50);
13952
-
14357
+
13953
14358
  this.createElements();
14359
+ this.initializePageCounter();
13954
14360
  this.initializePaginator();
13955
14361
  }else if(this.table.options.progressiveLoad){
13956
-
13957
14362
  this.subscribe("data-params", this.remotePageParams.bind(this));
13958
14363
  this.subscribe("data-loaded", this._parseRemoteData.bind(this));
13959
14364
  this.subscribe("table-built", this.calculatePageSizes.bind(this));
13960
-
14365
+ this.subscribe("data-processed", this.initialLoadComplete.bind(this));
14366
+
13961
14367
  this.initializeProgressive(this.table.options.progressiveLoad);
13962
-
14368
+
13963
14369
  if(this.table.options.progressiveLoad === "scroll"){
13964
14370
  this.subscribe("scroll-vertical", this.scrollVertical.bind(this));
13965
14371
  }
13966
14372
  }
13967
14373
  }
13968
-
14374
+
13969
14375
  rowAddingPosition(row, top){
13970
14376
  var rowManager = this.table.rowManager,
13971
14377
  dispRows = rowManager.getDisplayRows(),
13972
14378
  index;
13973
-
14379
+
13974
14380
  if(top){
13975
14381
  if(dispRows.length){
13976
14382
  index = dispRows[0];
@@ -13986,74 +14392,74 @@ class Page extends Module{
13986
14392
  top = dispRows.length < this.size ? false : true;
13987
14393
  }
13988
14394
  }
13989
-
14395
+
13990
14396
  return {index, top}
13991
14397
  }
13992
-
14398
+
13993
14399
  calculatePageSizes(){
13994
14400
  var testElRow, testElCell;
13995
-
14401
+
13996
14402
  if(this.table.options.paginationSize){
13997
14403
  this.size = this.table.options.paginationSize;
13998
14404
  }else {
13999
14405
  testElRow = document.createElement("div");
14000
14406
  testElRow.classList.add("tabulator-row");
14001
14407
  testElRow.style.visibility = "hidden";
14002
-
14408
+
14003
14409
  testElCell = document.createElement("div");
14004
14410
  testElCell.classList.add("tabulator-cell");
14005
14411
  testElCell.innerHTML = "Page Row Test";
14006
-
14412
+
14007
14413
  testElRow.appendChild(testElCell);
14008
-
14414
+
14009
14415
  this.table.rowManager.getTableElement().appendChild(testElRow);
14010
-
14416
+
14011
14417
  this.size = Math.floor(this.table.rowManager.getElement().clientHeight / testElRow.offsetHeight);
14012
-
14418
+
14013
14419
  this.table.rowManager.getTableElement().removeChild(testElRow);
14014
14420
  }
14015
-
14421
+
14016
14422
  this.generatePageSizeSelectList();
14017
14423
  }
14018
-
14424
+
14019
14425
  initialLoadComplete(){
14020
14426
  this.initialLoad = false;
14021
14427
  }
14022
-
14428
+
14023
14429
  remotePageParams(data, config, silent, params){
14024
14430
  if(!this.initialLoad){
14025
14431
  if((this.progressiveLoad && !silent) || (!this.progressiveLoad && !this.dataChanging)){
14026
14432
  this.reset(true);
14027
14433
  }
14028
14434
  }
14029
-
14435
+
14030
14436
  //configure request params
14031
14437
  params.page = this.page;
14032
-
14438
+
14033
14439
  //set page size if defined
14034
14440
  if(this.size){
14035
14441
  params.size = this.size;
14036
14442
  }
14037
-
14443
+
14038
14444
  return params;
14039
14445
  }
14040
-
14446
+
14041
14447
  ///////////////////////////////////
14042
14448
  ///////// Table Functions /////////
14043
14449
  ///////////////////////////////////
14044
-
14450
+
14045
14451
  userSetPageToRow(row){
14046
14452
  if(this.table.options.pagination){
14047
14453
  row = this.rowManager.findRow(row);
14048
-
14454
+
14049
14455
  if(row){
14050
14456
  return this.setPageToRow(row)
14051
14457
  }
14052
14458
  }
14053
-
14459
+
14054
14460
  return Promise.reject();
14055
14461
  }
14056
-
14462
+
14057
14463
  userSetPageSize(size){
14058
14464
  if(this.table.options.pagination){
14059
14465
  this.setPageSize(size);
@@ -14065,101 +14471,102 @@ class Page extends Module{
14065
14471
  ///////////////////////////////////
14066
14472
  ///////// Internal Logic //////////
14067
14473
  ///////////////////////////////////
14068
-
14474
+
14069
14475
  scrollVertical(top, dir){
14070
14476
  var element, diff, margin;
14071
14477
  if(!dir && !this.table.dataLoader.loading){
14072
14478
  element = this.table.rowManager.getElement();
14073
14479
  diff = element.scrollHeight - element.clientHeight - top;
14074
14480
  margin = this.table.options.progressiveLoadScrollMargin || (element.clientHeight * 2);
14075
-
14481
+
14076
14482
  if(diff < margin){
14077
- this.nextPage();
14483
+ this.nextPage()
14484
+ .catch(() => {}); //consume the exception thrown when on the last page
14078
14485
  }
14079
14486
  }
14080
14487
  }
14081
-
14488
+
14082
14489
  restOnRenderBefore(rows, renderInPosition){
14083
14490
  if(!renderInPosition){
14084
14491
  if(this.mode === "local"){
14085
14492
  this.reset();
14086
14493
  }
14087
14494
  }
14088
-
14495
+
14089
14496
  return rows;
14090
14497
  }
14091
-
14498
+
14092
14499
  rowsUpdated(){
14093
14500
  this.refreshData(true, "all");
14094
14501
  }
14095
-
14502
+
14096
14503
  createElements(){
14097
14504
  var button;
14098
-
14505
+
14099
14506
  this.element = document.createElement("span");
14100
14507
  this.element.classList.add("tabulator-paginator");
14101
-
14508
+
14102
14509
  this.pagesElement = document.createElement("span");
14103
14510
  this.pagesElement.classList.add("tabulator-pages");
14104
-
14511
+
14105
14512
  button = document.createElement("button");
14106
14513
  button.classList.add("tabulator-page");
14107
14514
  button.setAttribute("type", "button");
14108
14515
  button.setAttribute("role", "button");
14109
14516
  button.setAttribute("aria-label", "");
14110
14517
  button.setAttribute("title", "");
14111
-
14518
+
14112
14519
  this.firstBut = button.cloneNode(true);
14113
14520
  this.firstBut.setAttribute("data-page", "first");
14114
-
14521
+
14115
14522
  this.prevBut = button.cloneNode(true);
14116
14523
  this.prevBut.setAttribute("data-page", "prev");
14117
-
14524
+
14118
14525
  this.nextBut = button.cloneNode(true);
14119
14526
  this.nextBut.setAttribute("data-page", "next");
14120
-
14527
+
14121
14528
  this.lastBut = button.cloneNode(true);
14122
14529
  this.lastBut.setAttribute("data-page", "last");
14123
-
14530
+
14124
14531
  if(this.table.options.paginationSizeSelector){
14125
14532
  this.pageSizeSelect = document.createElement("select");
14126
14533
  this.pageSizeSelect.classList.add("tabulator-page-size");
14127
14534
  }
14128
14535
  }
14129
-
14536
+
14130
14537
  generatePageSizeSelectList(){
14131
14538
  var pageSizes = [];
14132
-
14539
+
14133
14540
  if(this.pageSizeSelect){
14134
-
14541
+
14135
14542
  if(Array.isArray(this.table.options.paginationSizeSelector)){
14136
14543
  pageSizes = this.table.options.paginationSizeSelector;
14137
14544
  this.pageSizes = pageSizes;
14138
-
14545
+
14139
14546
  if(this.pageSizes.indexOf(this.size) == -1){
14140
14547
  pageSizes.unshift(this.size);
14141
14548
  }
14142
14549
  }else {
14143
-
14550
+
14144
14551
  if(this.pageSizes.indexOf(this.size) == -1){
14145
14552
  pageSizes = [];
14146
-
14553
+
14147
14554
  for (let i = 1; i < 5; i++){
14148
14555
  pageSizes.push(this.size * i);
14149
14556
  }
14150
-
14557
+
14151
14558
  this.pageSizes = pageSizes;
14152
14559
  }else {
14153
14560
  pageSizes = this.pageSizes;
14154
14561
  }
14155
14562
  }
14156
-
14563
+
14157
14564
  while(this.pageSizeSelect.firstChild) this.pageSizeSelect.removeChild(this.pageSizeSelect.firstChild);
14158
-
14565
+
14159
14566
  pageSizes.forEach((item) => {
14160
14567
  var itemEl = document.createElement("option");
14161
14568
  itemEl.value = item;
14162
-
14569
+
14163
14570
  if(item === true){
14164
14571
  this.langBind("pagination|all", function(value){
14165
14572
  itemEl.innerHTML = value;
@@ -14167,136 +14574,178 @@ class Page extends Module{
14167
14574
  }else {
14168
14575
  itemEl.innerHTML = item;
14169
14576
  }
14170
-
14171
-
14172
-
14577
+
14578
+
14579
+
14173
14580
  this.pageSizeSelect.appendChild(itemEl);
14174
14581
  });
14175
-
14582
+
14176
14583
  this.pageSizeSelect.value = this.size;
14177
14584
  }
14178
14585
  }
14179
-
14180
- //setup pageination
14586
+
14587
+ initializePageCounter(){
14588
+ var counter = this.table.options.paginationCounter,
14589
+ pageCounter = null;
14590
+
14591
+ if(counter){
14592
+ if(typeof counter === "function"){
14593
+ pageCounter = counter;
14594
+ }else {
14595
+ pageCounter = Page.pageCounters[counter];
14596
+ }
14597
+
14598
+ if(pageCounter){
14599
+ this.pageCounter = pageCounter;
14600
+
14601
+ this.pageCounterElement = document.createElement("span");
14602
+ this.pageCounterElement.classList.add("tabulator-page-counter");
14603
+ }else {
14604
+ console.warn("Pagination Error - No such page counter found: ", counter);
14605
+ }
14606
+ }
14607
+ }
14608
+
14609
+ //setup pagination
14181
14610
  initializePaginator(hidden){
14182
- var pageSelectLabel;
14183
-
14611
+ var pageSelectLabel, paginationCounterHolder;
14612
+
14184
14613
  if(!hidden){
14185
14614
  //build pagination element
14186
-
14615
+
14187
14616
  //bind localizations
14188
14617
  this.langBind("pagination|first", (value) => {
14189
14618
  this.firstBut.innerHTML = value;
14190
14619
  });
14191
-
14620
+
14192
14621
  this.langBind("pagination|first_title", (value) => {
14193
14622
  this.firstBut.setAttribute("aria-label", value);
14194
14623
  this.firstBut.setAttribute("title", value);
14195
14624
  });
14196
-
14625
+
14197
14626
  this.langBind("pagination|prev", (value) => {
14198
14627
  this.prevBut.innerHTML = value;
14199
14628
  });
14200
-
14629
+
14201
14630
  this.langBind("pagination|prev_title", (value) => {
14202
14631
  this.prevBut.setAttribute("aria-label", value);
14203
14632
  this.prevBut.setAttribute("title", value);
14204
14633
  });
14205
-
14634
+
14206
14635
  this.langBind("pagination|next", (value) => {
14207
14636
  this.nextBut.innerHTML = value;
14208
14637
  });
14209
-
14638
+
14210
14639
  this.langBind("pagination|next_title", (value) => {
14211
14640
  this.nextBut.setAttribute("aria-label", value);
14212
14641
  this.nextBut.setAttribute("title", value);
14213
14642
  });
14214
-
14643
+
14215
14644
  this.langBind("pagination|last", (value) => {
14216
14645
  this.lastBut.innerHTML = value;
14217
14646
  });
14218
-
14647
+
14219
14648
  this.langBind("pagination|last_title", (value) => {
14220
14649
  this.lastBut.setAttribute("aria-label", value);
14221
14650
  this.lastBut.setAttribute("title", value);
14222
14651
  });
14223
-
14652
+
14224
14653
  //click bindings
14225
14654
  this.firstBut.addEventListener("click", () => {
14226
14655
  this.setPage(1);
14227
14656
  });
14228
-
14657
+
14229
14658
  this.prevBut.addEventListener("click", () => {
14230
14659
  this.previousPage();
14231
14660
  });
14232
-
14661
+
14233
14662
  this.nextBut.addEventListener("click", () => {
14234
14663
  this.nextPage();
14235
14664
  });
14236
-
14665
+
14237
14666
  this.lastBut.addEventListener("click", () => {
14238
14667
  this.setPage(this.max);
14239
14668
  });
14240
-
14669
+
14241
14670
  if(this.table.options.paginationElement){
14242
14671
  this.element = this.table.options.paginationElement;
14243
14672
  }
14244
-
14673
+
14245
14674
  if(this.pageSizeSelect){
14246
14675
  pageSelectLabel = document.createElement("label");
14247
-
14676
+
14248
14677
  this.langBind("pagination|page_size", (value) => {
14249
14678
  this.pageSizeSelect.setAttribute("aria-label", value);
14250
14679
  this.pageSizeSelect.setAttribute("title", value);
14251
14680
  pageSelectLabel.innerHTML = value;
14252
14681
  });
14253
-
14682
+
14254
14683
  this.element.appendChild(pageSelectLabel);
14255
14684
  this.element.appendChild(this.pageSizeSelect);
14256
-
14685
+
14257
14686
  this.pageSizeSelect.addEventListener("change", (e) => {
14258
14687
  this.setPageSize(this.pageSizeSelect.value == "true" ? true : this.pageSizeSelect.value);
14259
14688
  this.setPage(1);
14260
14689
  });
14261
14690
  }
14262
-
14691
+
14263
14692
  //append to DOM
14264
14693
  this.element.appendChild(this.firstBut);
14265
14694
  this.element.appendChild(this.prevBut);
14266
14695
  this.element.appendChild(this.pagesElement);
14267
14696
  this.element.appendChild(this.nextBut);
14268
14697
  this.element.appendChild(this.lastBut);
14269
-
14698
+
14270
14699
  if(!this.table.options.paginationElement && !hidden){
14700
+ if(this.table.options.paginationCounter){
14701
+
14702
+ if(this.table.options.paginationCounterElement){
14703
+ if(this.table.options.paginationCounterElement instanceof HTMLElement){
14704
+ this.table.options.paginationCounterElement.appendChild(this.pageCounterElement);
14705
+ }else if(typeof this.table.options.paginationCounterElement === "string"){
14706
+ paginationCounterHolder = document.querySelector(this.table.options.paginationCounterElement);
14707
+
14708
+ if(paginationCounterHolder){
14709
+ paginationCounterHolder.appendChild(this.pageCounterElement);
14710
+ }else {
14711
+ console.warn("Pagination Error - Unable to find element matching paginationCounterElement selector:", this.table.options.paginationCounterElement);
14712
+ }
14713
+ }
14714
+ }else {
14715
+ this.table.footerManager.append(this.pageCounterElement);
14716
+ }
14717
+
14718
+ }
14719
+
14271
14720
  this.table.footerManager.append(this.element, this);
14272
14721
  }
14273
-
14722
+
14274
14723
  this.page = this.table.options.paginationInitialPage;
14275
14724
  this.count = this.table.options.paginationButtonCount;
14276
14725
  }
14277
-
14726
+
14278
14727
  //set default values
14279
14728
  this.mode = this.table.options.paginationMode;
14280
14729
  }
14281
-
14730
+
14282
14731
  initializeProgressive(mode){
14283
14732
  this.initializePaginator(true);
14284
14733
  this.mode = "progressive_" + mode;
14285
14734
  this.progressiveLoad = true;
14286
14735
  }
14287
-
14736
+
14288
14737
  trackChanges(){
14289
14738
  this.dispatch("page-changed");
14290
14739
  }
14291
-
14740
+
14292
14741
  setDisplayIndex(index){
14293
14742
  this.displayIndex = index;
14294
14743
  }
14295
-
14744
+
14296
14745
  getDisplayIndex(){
14297
14746
  return this.displayIndex;
14298
14747
  }
14299
-
14748
+
14300
14749
  //calculate maximum page from number of rows
14301
14750
  setMaxRows(rowCount){
14302
14751
  if(!rowCount){
@@ -14304,12 +14753,12 @@ class Page extends Module{
14304
14753
  }else {
14305
14754
  this.max = this.size === true ? 1 : Math.ceil(rowCount/this.size);
14306
14755
  }
14307
-
14756
+
14308
14757
  if(this.page > this.max){
14309
14758
  this.page = this.max;
14310
14759
  }
14311
14760
  }
14312
-
14761
+
14313
14762
  //reset to first page without triggering action
14314
14763
  reset(force){
14315
14764
  if(!this.initialLoad){
@@ -14318,91 +14767,128 @@ class Page extends Module{
14318
14767
  }
14319
14768
  }
14320
14769
  }
14321
-
14322
- //set the maxmum page
14770
+
14771
+ //set the maximum page
14323
14772
  setMaxPage(max){
14324
-
14773
+
14325
14774
  max = parseInt(max);
14326
-
14775
+
14327
14776
  this.max = max || 1;
14328
-
14777
+
14329
14778
  if(this.page > this.max){
14330
14779
  this.page = this.max;
14331
14780
  this.trigger();
14332
14781
  }
14333
14782
  }
14334
-
14783
+
14335
14784
  //set current page number
14336
14785
  setPage(page){
14337
14786
  switch(page){
14338
14787
  case "first":
14339
14788
  return this.setPage(1);
14340
-
14789
+
14341
14790
  case "prev":
14342
14791
  return this.previousPage();
14343
-
14792
+
14344
14793
  case "next":
14345
14794
  return this.nextPage();
14346
-
14795
+
14347
14796
  case "last":
14348
14797
  return this.setPage(this.max);
14349
14798
  }
14350
-
14351
-
14799
+
14352
14800
  page = parseInt(page);
14353
-
14801
+
14354
14802
  if((page > 0 && page <= this.max) || this.mode !== "local"){
14355
14803
  this.page = page;
14356
-
14804
+
14357
14805
  this.trackChanges();
14358
-
14806
+
14359
14807
  return this.trigger();
14360
14808
  }else {
14361
14809
  console.warn("Pagination Error - Requested page is out of range of 1 - " + this.max + ":", page);
14362
14810
  return Promise.reject();
14363
14811
  }
14364
14812
  }
14365
-
14813
+
14366
14814
  setPageToRow(row){
14367
14815
  var rows = this.table.rowManager.getDisplayRows(this.displayIndex - 1);
14368
14816
  var index = rows.indexOf(row);
14369
-
14817
+
14370
14818
  if(index > -1){
14371
14819
  var page = this.size === true ? 1 : Math.ceil((index + 1) / this.size);
14372
-
14820
+
14373
14821
  return this.setPage(page)
14374
14822
  }else {
14375
14823
  console.warn("Pagination Error - Requested row is not visible");
14376
14824
  return Promise.reject();
14377
14825
  }
14378
14826
  }
14379
-
14827
+
14380
14828
  setPageSize(size){
14381
14829
  if(size !== true){
14382
14830
  size = parseInt(size);
14383
14831
  }
14384
-
14832
+
14385
14833
  if(size > 0){
14386
14834
  this.size = size;
14387
14835
  }
14388
-
14836
+
14389
14837
  if(this.pageSizeSelect){
14390
14838
  // this.pageSizeSelect.value = size;
14391
14839
  this.generatePageSizeSelectList();
14392
14840
  }
14393
-
14841
+
14394
14842
  this.trackChanges();
14395
14843
  }
14844
+
14845
+ _setPageCounter(totalRows){
14846
+ var content, currentRow;
14847
+
14848
+ if(this.pageCounter){
14849
+ currentRow = ((this.page - 1) * this.size) + 1;
14850
+
14851
+ if(this.mode === "remote"){
14852
+ totalRows = this.remoteRowCountEstimate;
14853
+ }
14396
14854
 
14855
+ content = this.pageCounter.call(this, this.size, currentRow, this.page, totalRows, this.max);
14856
+
14857
+ switch(typeof content){
14858
+ case "object":
14859
+ if(content instanceof Node){
14860
+
14861
+ //clear previous cell contents
14862
+ while(this.pageCounterElement.firstChild) this.pageCounterElement.removeChild(this.pageCounterElement.firstChild);
14863
+
14864
+ this.pageCounterElement.appendChild(content);
14865
+ }else {
14866
+ this.pageCounterElement.innerHTML = "";
14867
+
14868
+ if(content != null){
14869
+ console.warn("Page Counter Error - Page Counter has returned a type of object, the only valid page counter object return is an instance of Node, the page counter returned:", content);
14870
+ }
14871
+ }
14872
+ break;
14873
+ case "undefined":
14874
+ case "null":
14875
+ this.pageCounterElement.innerHTML = "";
14876
+ break;
14877
+ default:
14878
+ this.pageCounterElement.innerHTML = content;
14879
+ }
14880
+ }
14881
+ }
14882
+
14397
14883
  //setup the pagination buttons
14398
14884
  _setPageButtons(){
14399
14885
  let leftSize = Math.floor((this.count-1) / 2);
14400
14886
  let rightSize = Math.ceil((this.count-1) / 2);
14401
14887
  let min = this.max - this.page + leftSize + 1 < this.count ? this.max-this.count+1: Math.max(this.page-leftSize,1);
14402
14888
  let max = this.page <= rightSize? Math.min(this.count, this.max) :Math.min(this.page+rightSize, this.max);
14403
-
14889
+
14404
14890
  while(this.pagesElement.firstChild) this.pagesElement.removeChild(this.pagesElement.firstChild);
14405
-
14891
+
14406
14892
  if(this.page == 1){
14407
14893
  this.firstBut.disabled = true;
14408
14894
  this.prevBut.disabled = true;
@@ -14410,7 +14896,7 @@ class Page extends Module{
14410
14896
  this.firstBut.disabled = false;
14411
14897
  this.prevBut.disabled = false;
14412
14898
  }
14413
-
14899
+
14414
14900
  if(this.page == this.max){
14415
14901
  this.lastBut.disabled = true;
14416
14902
  this.nextBut.disabled = true;
@@ -14418,66 +14904,66 @@ class Page extends Module{
14418
14904
  this.lastBut.disabled = false;
14419
14905
  this.nextBut.disabled = false;
14420
14906
  }
14421
-
14907
+
14422
14908
  for(let i = min; i <= max; i++){
14423
14909
  if(i>0 && i <= this.max){
14424
14910
  this.pagesElement.appendChild(this._generatePageButton(i));
14425
14911
  }
14426
14912
  }
14427
-
14913
+
14428
14914
  this.footerRedraw();
14429
14915
  }
14430
-
14916
+
14431
14917
  _generatePageButton(page){
14432
14918
  var button = document.createElement("button");
14433
-
14919
+
14434
14920
  button.classList.add("tabulator-page");
14435
14921
  if(page == this.page){
14436
14922
  button.classList.add("active");
14437
14923
  }
14438
-
14924
+
14439
14925
  button.setAttribute("type", "button");
14440
14926
  button.setAttribute("role", "button");
14441
-
14927
+
14442
14928
  this.langBind("pagination|page_title", (value) => {
14443
14929
  button.setAttribute("aria-label", value + " " + page);
14444
14930
  button.setAttribute("title", value + " " + page);
14445
14931
  });
14446
-
14932
+
14447
14933
  button.setAttribute("data-page", page);
14448
14934
  button.textContent = page;
14449
-
14935
+
14450
14936
  button.addEventListener("click", (e) => {
14451
14937
  this.setPage(page);
14452
14938
  });
14453
-
14939
+
14454
14940
  return button;
14455
14941
  }
14456
-
14942
+
14457
14943
  //previous page
14458
14944
  previousPage(){
14459
14945
  if(this.page > 1){
14460
14946
  this.page--;
14461
-
14947
+
14462
14948
  this.trackChanges();
14463
-
14949
+
14464
14950
  return this.trigger()
14465
-
14951
+
14466
14952
  }else {
14467
14953
  console.warn("Pagination Error - Previous page would be less than page 1:", 0);
14468
14954
  return Promise.reject();
14469
14955
  }
14470
14956
  }
14471
-
14957
+
14472
14958
  //next page
14473
14959
  nextPage(){
14474
14960
  if(this.page < this.max){
14475
14961
  this.page++;
14476
-
14962
+
14477
14963
  this.trackChanges();
14478
-
14964
+
14479
14965
  return this.trigger();
14480
-
14966
+
14481
14967
  }else {
14482
14968
  if(!this.progressiveLoad){
14483
14969
  console.warn("Pagination Error - Next page would be greater than maximum page of " + this.max + ":", this.max + 1);
@@ -14485,34 +14971,34 @@ class Page extends Module{
14485
14971
  return Promise.reject();
14486
14972
  }
14487
14973
  }
14488
-
14974
+
14489
14975
  //return current page number
14490
14976
  getPage(){
14491
14977
  return this.page;
14492
14978
  }
14493
-
14979
+
14494
14980
  //return max page number
14495
14981
  getPageMax(){
14496
14982
  return this.max;
14497
14983
  }
14498
-
14984
+
14499
14985
  getPageSize(size){
14500
14986
  return this.size;
14501
14987
  }
14502
-
14988
+
14503
14989
  getMode(){
14504
14990
  return this.mode;
14505
14991
  }
14506
-
14992
+
14507
14993
  //return appropriate rows for current page
14508
14994
  getRows(data){
14509
14995
  var output, start, end;
14510
-
14996
+
14511
14997
  if(this.mode == "local"){
14512
14998
  output = [];
14513
-
14999
+
14514
15000
  this.setMaxRows(data.length);
14515
-
15001
+
14516
15002
  if(this.size === true){
14517
15003
  start = 0;
14518
15004
  end = data.length;
@@ -14520,89 +15006,94 @@ class Page extends Module{
14520
15006
  start = this.size * (this.page - 1);
14521
15007
  end = start + parseInt(this.size);
14522
15008
  }
14523
-
14524
-
15009
+
15010
+
14525
15011
  this._setPageButtons();
14526
-
15012
+
14527
15013
  for(let i = start; i < end; i++){
14528
15014
  if(data[i]){
14529
15015
  output.push(data[i]);
14530
15016
  }
14531
15017
  }
14532
15018
 
15019
+ this._setPageCounter(data.length);
15020
+
14533
15021
  return output;
14534
15022
  }else {
14535
15023
  this._setPageButtons();
14536
-
15024
+ this._setPageCounter(data.length);
15025
+
14537
15026
  return data.slice(0);
14538
15027
  }
14539
15028
  }
14540
-
15029
+
14541
15030
  trigger(){
14542
15031
  var left;
14543
-
15032
+
14544
15033
  switch(this.mode){
14545
15034
  case "local":
14546
15035
  left = this.table.rowManager.scrollLeft;
14547
-
15036
+
14548
15037
  this.refreshData();
14549
15038
  this.table.rowManager.scrollHorizontal(left);
14550
-
15039
+
14551
15040
  this.dispatchExternal("pageLoaded", this.getPage());
14552
-
15041
+
14553
15042
  return Promise.resolve();
14554
-
15043
+
14555
15044
  case "remote":
14556
15045
  this.dataChanging = true;
14557
15046
  return this.reloadData(null)
14558
15047
  .finally(() => {
14559
15048
  this.dataChanging = false;
14560
15049
  })
14561
-
15050
+
14562
15051
  case "progressive_load":
14563
15052
  case "progressive_scroll":
14564
15053
  return this.reloadData(null, true);
14565
-
15054
+
14566
15055
  default:
14567
15056
  console.warn("Pagination Error - no such pagination mode:", this.mode);
14568
15057
  return Promise.reject();
14569
15058
  }
14570
15059
  }
14571
-
15060
+
14572
15061
  _parseRemoteData(data){
14573
15062
  var data, margin;
14574
-
15063
+
14575
15064
  if(typeof data.last_page === "undefined"){
14576
- console.warn("Remote Pagination Error - Server response missing '" + this.dataReceivedNames.last_page + "' property");
15065
+ console.warn("Remote Pagination Error - Server response missing '" + (this.options("dataReceiveParams").last_page || "last_page") + "' property");
14577
15066
  }
14578
-
15067
+
14579
15068
  if(data.data){
14580
15069
  this.max = parseInt(data.last_page) || 1;
14581
15070
 
15071
+ this.remoteRowCountEstimate = typeof data.last_row !== "undefined" ? data.last_row : (data.last_page * this.size - (this.page == data.last_page ? (this.size - data.data.length) : 0));
15072
+
14582
15073
  if(this.progressiveLoad){
14583
15074
  switch(this.mode){
14584
15075
  case "progressive_load":
14585
-
15076
+
14586
15077
  if(this.page == 1){
14587
15078
  this.table.rowManager.setData(data.data, false, this.page == 1);
14588
15079
  }else {
14589
15080
  this.table.rowManager.addRows(data.data);
14590
15081
  }
14591
-
15082
+
14592
15083
  if(this.page < this.max){
14593
15084
  setTimeout(() => {
14594
15085
  this.nextPage();
14595
15086
  }, this.table.options.progressiveLoadDelay);
14596
15087
  }
14597
15088
  break;
14598
-
15089
+
14599
15090
  case "progressive_scroll":
14600
- data = this.table.rowManager.getData().concat(data.data);
14601
-
15091
+ data = this.page === 1 ? data.data : this.table.rowManager.getData().concat(data.data);
15092
+
14602
15093
  this.table.rowManager.setData(data, this.page !== 1, this.page == 1);
14603
-
15094
+
14604
15095
  margin = this.table.options.progressiveLoadScrollMargin || (this.table.rowManager.element.clientHeight * 2);
14605
-
15096
+
14606
15097
  if(this.table.rowManager.element.scrollHeight <= (this.table.rowManager.element.clientHeight + margin)){
14607
15098
  setTimeout(() => {
14608
15099
  this.nextPage();
@@ -14610,7 +15101,7 @@ class Page extends Module{
14610
15101
  }
14611
15102
  break;
14612
15103
  }
14613
-
15104
+
14614
15105
  return false;
14615
15106
  }else {
14616
15107
  // left = this.table.rowManager.scrollLeft;
@@ -14618,23 +15109,23 @@ class Page extends Module{
14618
15109
  // this.table.rowManager.scrollHorizontal(left);
14619
15110
  // this.table.columnManager.scrollHorizontal(left);
14620
15111
  }
14621
-
15112
+
14622
15113
  }else {
14623
- console.warn("Remote Pagination Error - Server response missing '" + this.dataReceivedNames.data + "' property");
15114
+ console.warn("Remote Pagination Error - Server response missing '" + (this.options("dataReceiveParams").data || "data") + "' property");
14624
15115
  }
14625
-
15116
+
14626
15117
  return data.data;
14627
15118
  }
14628
-
15119
+
14629
15120
  //handle the footer element being redrawn
14630
15121
  footerRedraw(){
14631
15122
  var footer = this.table.footerManager.element;
14632
-
15123
+
14633
15124
  if((Math.ceil(footer.clientWidth) - footer.scrollWidth) < 0){
14634
15125
  this.pagesElement.style.display = 'none';
14635
15126
  }else {
14636
15127
  this.pagesElement.style.display = '';
14637
-
15128
+
14638
15129
  if((Math.ceil(footer.clientWidth) - footer.scrollWidth) < 0){
14639
15130
  this.pagesElement.style.display = 'none';
14640
15131
  }
@@ -14642,7 +15133,10 @@ class Page extends Module{
14642
15133
  }
14643
15134
  }
14644
15135
 
14645
- Page.moduleName = "page";
15136
+ Page.moduleName = "page";
15137
+
15138
+ //load defaults
15139
+ Page.pageCounters = defaultPageCounters;
14646
15140
 
14647
15141
  // read peristence information from storage
14648
15142
  var defaultReaders = {
@@ -15874,7 +16368,7 @@ class ResizeRows extends Module{
15874
16368
 
15875
16369
  self.table.element.classList.remove("tabulator-block-select");
15876
16370
 
15877
- this.dispatchExternal("rowResized", row.getComponent());
16371
+ self.dispatchExternal("rowResized", row.getComponent());
15878
16372
  }
15879
16373
 
15880
16374
  e.stopPropagation(); //prevent resize from interfereing with movable columns
@@ -16045,7 +16539,7 @@ class ResponsiveLayout extends Module{
16045
16539
  this.registerColumnOption("responsive");
16046
16540
  }
16047
16541
 
16048
- //generate resposive columns list
16542
+ //generate responsive columns list
16049
16543
  initialize(){
16050
16544
 
16051
16545
  if(this.table.options.responsiveLayout){
@@ -16082,7 +16576,7 @@ class ResponsiveLayout extends Module{
16082
16576
  this.collapseStartOpen = this.table.options.responsiveLayoutCollapseStartOpen;
16083
16577
  this.hiddenColumns = [];
16084
16578
 
16085
- //detemine level of responsivity for each column
16579
+ //determine level of responsivity for each column
16086
16580
  this.table.columnManager.columnsByIndex.forEach(function(column, i){
16087
16581
  if(column.modules.responsive){
16088
16582
  if(column.modules.responsive.order && column.modules.responsive.visible){
@@ -16164,10 +16658,8 @@ class ResponsiveLayout extends Module{
16164
16658
  updateColumnVisibility(column, responsiveToggle){
16165
16659
  if(!responsiveToggle && column.modules.responsive){
16166
16660
  column.modules.responsive.visible = column.visible;
16167
- this.initialize();
16661
+ this.initializeResponsivity();
16168
16662
  }
16169
-
16170
- //this.update();
16171
16663
  }
16172
16664
 
16173
16665
  hideColumn(column){
@@ -16405,7 +16897,7 @@ class SelectRow extends Module{
16405
16897
  this.subscribe("rows-wipe", this.clearSelectionData.bind(this));
16406
16898
  this.subscribe("rows-retrieve", this.rowRetrieve.bind(this));
16407
16899
 
16408
- if(this.table.options.selectable && this.table.options.selectablePersistence){
16900
+ if(this.table.options.selectable && !this.table.options.selectablePersistence){
16409
16901
  this.subscribe("data-refeshing", this.deselectRows.bind(this));
16410
16902
  }
16411
16903
  }
@@ -16644,9 +17136,7 @@ class SelectRow extends Module{
16644
17136
  this.childRowSelection(row, true);
16645
17137
  }
16646
17138
 
16647
- if(!silent){
16648
- this.dispatchExternal("rowSelected", row.getComponent());
16649
- }
17139
+ this.dispatchExternal("rowSelected", row.getComponent());
16650
17140
 
16651
17141
  this._rowSelectionChanged(silent);
16652
17142
  }
@@ -16665,7 +17155,7 @@ class SelectRow extends Module{
16665
17155
  deselectRows(rows, silent){
16666
17156
  var self = this,
16667
17157
  rowCount;
16668
-
17158
+
16669
17159
  if(typeof rows == "undefined"){
16670
17160
 
16671
17161
  rowCount = self.selectedRows.length;
@@ -16717,9 +17207,7 @@ class SelectRow extends Module{
16717
17207
  this.childRowSelection(row, false);
16718
17208
  }
16719
17209
 
16720
- if(!silent){
16721
- this.dispatchExternal("rowDeselected", row.getComponent());
16722
- }
17210
+ this.dispatchExternal("rowDeselected", row.getComponent());
16723
17211
 
16724
17212
  self._rowSelectionChanged(silent);
16725
17213
  }
@@ -16883,8 +17371,9 @@ function datetime$1(a, b, aRow, bRow, column, dir, params){
16883
17371
  emptyAlign = 0;
16884
17372
 
16885
17373
  if(typeof DT != "undefined"){
16886
- a = DT.fromFormat(a, format);
16887
- b = DT.fromFormat(b, format);
17374
+ a = format === "iso" ? DT.fromISO(String(a)) : DT.fromFormat(String(a), format);
17375
+ b = format === "iso" ? DT.fromISO(String(b)) : DT.fromFormat(String(b), format);
17376
+
16888
17377
  if(!a.isValid){
16889
17378
  emptyAlign = !b.isValid ? 0 : -1;
16890
17379
  }else if(!b.isValid){
@@ -17255,7 +17744,7 @@ class Sort extends Module{
17255
17744
  if(this.table.options.sortMode === "remote"){
17256
17745
  this.reloadData();
17257
17746
  }else {
17258
- this.refreshData();
17747
+ this.refreshData(true);
17259
17748
  }
17260
17749
 
17261
17750
  //TODO - Persist left position of row manager
@@ -17659,7 +18148,7 @@ class Validate extends Module{
17659
18148
  columnValidate(column){
17660
18149
  var invalid = [];
17661
18150
 
17662
- column.cells.forEach(function(cell){
18151
+ column.cells.forEach((cell) => {
17663
18152
  if(!this.cellValidate(cell)){
17664
18153
  invalid.push(cell.getComponent());
17665
18154
  }
@@ -17675,7 +18164,7 @@ class Validate extends Module{
17675
18164
  rowValidate(row){
17676
18165
  var invalid = [];
17677
18166
 
17678
- row.cells.forEach(function(cell){
18167
+ row.cells.forEach((cell) => {
17679
18168
  if(!this.cellValidate(cell)){
17680
18169
  invalid.push(cell.getComponent());
17681
18170
  }
@@ -17707,7 +18196,9 @@ class Validate extends Module{
17707
18196
  var output = [];
17708
18197
 
17709
18198
  //clear row data
17710
- this.table.rowManager.rows.forEach(function(row){
18199
+ this.table.rowManager.rows.forEach((row) => {
18200
+ row = row.getComponent();
18201
+
17711
18202
  var valid = row.validate();
17712
18203
 
17713
18204
  if(valid !== true){
@@ -17737,7 +18228,7 @@ class Validate extends Module{
17737
18228
  if(column.definition.validator){
17738
18229
 
17739
18230
  if(Array.isArray(column.definition.validator)){
17740
- column.definition.validator.forEach(function(item){
18231
+ column.definition.validator.forEach((item) => {
17741
18232
  validator = self._extractValidator(item);
17742
18233
 
17743
18234
  if(validator){
@@ -17803,7 +18294,7 @@ class Validate extends Module{
17803
18294
  invalidIndex = this.invalidCells.indexOf(cell);
17804
18295
 
17805
18296
  if(validators){
17806
- validators.forEach(function(item){
18297
+ validators.forEach((item) => {
17807
18298
  if(!item.func.call(self, cell.getComponent(), value, item.params)){
17808
18299
  valid.push({
17809
18300
  type:item.type,
@@ -17890,6 +18381,7 @@ var modules = /*#__PURE__*/Object.freeze({
17890
18381
  GroupRowsModule: GroupRows,
17891
18382
  HistoryModule: History,
17892
18383
  HtmlTableImportModule: HtmlTableImport,
18384
+ ImportModule: Import,
17893
18385
  InteractionModule: Interaction,
17894
18386
  KeybindingsModule: Keybindings,
17895
18387
  MenuModule: Menu,
@@ -17909,7 +18401,7 @@ var modules = /*#__PURE__*/Object.freeze({
17909
18401
  ValidateModule: Validate
17910
18402
  });
17911
18403
 
17912
- var defaultOptions$1 = {
18404
+ var defaultOptions = {
17913
18405
 
17914
18406
  debugEventsExternal:false, //flag to console log events
17915
18407
  debugEventsInternal:false, //flag to console log events
@@ -17919,7 +18411,6 @@ var defaultOptions$1 = {
17919
18411
  minHeight:false, //minimum height of tabulator
17920
18412
  maxHeight:false, //maximum height of tabulator
17921
18413
 
17922
- columnMaxWidth:false, //minimum global width for a column
17923
18414
  columnHeaderVertAlign:"top", //vertical alignment of column headers
17924
18415
 
17925
18416
  columns:[],//store for colum header info
@@ -17930,7 +18421,7 @@ var defaultOptions$1 = {
17930
18421
  autoColumns:false, //build columns from data row structure
17931
18422
  autoColumnsDefinitions:false,
17932
18423
 
17933
- nestedFieldSeparator:".", //seperatpr for nested data
18424
+ nestedFieldSeparator:".", //separator for nested data
17934
18425
 
17935
18426
  tooltipGenerationMode:"load", //when to generate tooltips
17936
18427
 
@@ -17964,6 +18455,7 @@ var defaultOptions$1 = {
17964
18455
  dataLoader:true,
17965
18456
  dataLoaderLoading:false,
17966
18457
  dataLoaderError:false,
18458
+ dataLoaderErrorTimeout:3000,
17967
18459
 
17968
18460
  dataSendParams:{},
17969
18461
 
@@ -17971,10 +18463,10 @@ var defaultOptions$1 = {
17971
18463
  };
17972
18464
 
17973
18465
  class OptionsList {
17974
- constructor(table, msgType){
18466
+ constructor(table, msgType, defaults = {}){
17975
18467
  this.table = table;
17976
18468
  this.msgType = msgType;
17977
- this.registeredDefaults = {};
18469
+ this.registeredDefaults = Object.assign({}, defaults);
17978
18470
  }
17979
18471
 
17980
18472
  register(option, value){
@@ -18090,7 +18582,7 @@ class Renderer extends CoreFeature{
18090
18582
  }
18091
18583
 
18092
18584
  scrollToRowNearestTop(row){
18093
- //determin weather the row is nearest the top or bottom of the table, retur true for top or false for bottom
18585
+ //determine weather the row is nearest the top or bottom of the table, retur true for top or false for bottom
18094
18586
  }
18095
18587
 
18096
18588
  visibleRows(includingBuffer){
@@ -18157,8 +18649,9 @@ class Renderer extends CoreFeature{
18157
18649
  if(!ifVisible){
18158
18650
  if(Helpers.elVisible(rowEl)){
18159
18651
  offset = Helpers.elOffset(rowEl).top - Helpers.elOffset(this.elementVertical).top;
18160
-
18652
+
18161
18653
  if(offset > 0 && offset < this.elementVertical.clientHeight - rowEl.offsetHeight){
18654
+ resolve();
18162
18655
  return false;
18163
18656
  }
18164
18657
  }
@@ -18231,157 +18724,157 @@ class BaiscHorizontal extends Renderer{
18231
18724
  class VirtualDomHorizontal extends Renderer{
18232
18725
  constructor(table){
18233
18726
  super(table);
18234
-
18727
+
18235
18728
  this.leftCol = 0;
18236
18729
  this.rightCol = 0;
18237
18730
  this.scrollLeft = 0;
18238
-
18731
+
18239
18732
  this.vDomScrollPosLeft = 0;
18240
18733
  this.vDomScrollPosRight = 0;
18241
-
18734
+
18242
18735
  this.vDomPadLeft = 0;
18243
18736
  this.vDomPadRight = 0;
18244
-
18737
+
18245
18738
  this.fitDataColAvg = 0;
18246
-
18739
+
18247
18740
  this.window = 200; //pixel margin to make column visible before it is shown on screen
18248
-
18741
+
18249
18742
  this.initialized = false;
18250
-
18743
+
18251
18744
  this.columns = [];
18252
18745
  }
18253
-
18746
+
18254
18747
  initialize(){
18255
- this.compatabilityCheck();
18748
+ this.compatibilityCheck();
18256
18749
  }
18257
-
18258
- compatabilityCheck(){
18750
+
18751
+ compatibilityCheck(){
18259
18752
  var columns = this.options("columns"),
18260
18753
  frozen = false,
18261
18754
  ok = true;
18262
-
18755
+
18263
18756
  if(this.options("layout") == "fitDataTable"){
18264
- console.warn("Horizontal Vitrual DOM is not compatible with fitDataTable layout mode");
18757
+ console.warn("Horizontal Virtual DOM is not compatible with fitDataTable layout mode");
18265
18758
  ok = false;
18266
18759
  }
18267
-
18760
+
18268
18761
  if(this.options("responsiveLayout")){
18269
- console.warn("Horizontal Vitrual DOM is not compatible with responsive columns");
18762
+ console.warn("Horizontal Virtual DOM is not compatible with responsive columns");
18270
18763
  ok = false;
18271
18764
  }
18272
-
18765
+
18273
18766
  if(this.options("rtl")){
18274
- console.warn("Horizontal Vitrual DOM is not currently compatible with RTL text direction");
18767
+ console.warn("Horizontal Virtual DOM is not currently compatible with RTL text direction");
18275
18768
  ok = false;
18276
18769
  }
18277
-
18770
+
18278
18771
  if(columns){
18279
18772
  frozen = columns.find((col) => {
18280
18773
  return col.frozen;
18281
18774
  });
18282
-
18775
+
18283
18776
  if(frozen){
18284
- console.warn("Horizontal Vitrual DOM is not compatible with frozen columns");
18777
+ console.warn("Horizontal Virtual DOM is not compatible with frozen columns");
18285
18778
  ok = false;
18286
18779
  }
18287
18780
  }
18288
-
18781
+
18289
18782
  // if(!ok){
18290
18783
  // options.virtualDomHoz = false;
18291
18784
  // }
18292
-
18785
+
18293
18786
  return ok;
18294
18787
  }
18295
-
18788
+
18296
18789
  //////////////////////////////////////
18297
18790
  ///////// Public Functions ///////////
18298
18791
  //////////////////////////////////////
18299
-
18792
+
18300
18793
  renderColumns(row, force){
18301
18794
  this.dataChange();
18302
18795
  }
18303
-
18796
+
18304
18797
  scrollColumns(left, dir){
18305
18798
  if(this.scrollLeft != left){
18306
18799
  this.scrollLeft = left;
18307
-
18800
+
18308
18801
  this.scroll(left - (this.vDomScrollPosLeft + this.window));
18309
18802
  }
18310
18803
  }
18311
-
18312
- rerenderColumns(update, blockRedraw){
18804
+
18805
+ rerenderColumns(update, blockRedraw){
18313
18806
  var old = {
18314
18807
  cols:this.columns,
18315
18808
  leftCol:this.leftCol,
18316
18809
  rightCol:this.rightCol,
18317
18810
  };
18318
-
18811
+
18319
18812
  if(update && !this.initialized){
18320
18813
  return;
18321
18814
  }
18322
-
18815
+
18323
18816
  this.clear();
18324
-
18817
+
18325
18818
  this.scrollLeft = this.elementVertical.scrollLeft;
18326
-
18819
+
18327
18820
  this.vDomScrollPosLeft = this.scrollLeft - this.window;
18328
18821
  this.vDomScrollPosRight = this.scrollLeft + this.elementVertical.clientWidth + this.window;
18329
-
18822
+
18330
18823
  var colPos = 0;
18331
-
18824
+
18332
18825
  this.table.columnManager.columnsByIndex.forEach((column) => {
18333
18826
  var config = {};
18334
-
18827
+
18335
18828
  if(column.visible){
18336
18829
  var width = column.getWidth();
18337
-
18830
+
18338
18831
  config.leftPos = colPos;
18339
18832
  config.rightPos = colPos + width;
18340
-
18833
+
18341
18834
  config.width = width;
18342
-
18835
+
18343
18836
  if (this.options("layout") === "fitData") {
18344
- config.fitDataCheck = true;
18837
+ config.fitDataCheck = column.modules.vdomHoz ? column.modules.vdomHoz.fitDataCheck : true;
18345
18838
  }
18346
-
18839
+
18347
18840
  if((colPos + width > this.vDomScrollPosLeft) && (colPos < this.vDomScrollPosRight)){
18348
- //column is visible
18349
-
18350
- if(this.leftCol == -1){
18351
- this.leftCol = this.columns.length;
18352
- this.vDomPadLeft = colPos;
18353
- }
18354
-
18355
- this.rightCol = this.columns.length;
18356
- }else {
18357
- // column is hidden
18358
- if(this.leftCol !== -1){
18359
- this.vDomPadRight += width;
18360
- }
18361
- }
18362
-
18363
- this.columns.push(column);
18364
-
18365
- column.modules.vdomHoz = config;
18366
-
18367
- colPos += width;
18368
- }
18369
- });
18370
-
18841
+ //column is visible
18842
+
18843
+ if(this.leftCol == -1){
18844
+ this.leftCol = this.columns.length;
18845
+ this.vDomPadLeft = colPos;
18846
+ }
18847
+
18848
+ this.rightCol = this.columns.length;
18849
+ }else {
18850
+ // column is hidden
18851
+ if(this.leftCol !== -1){
18852
+ this.vDomPadRight += width;
18853
+ }
18854
+ }
18855
+
18856
+ this.columns.push(column);
18857
+
18858
+ column.modules.vdomHoz = config;
18859
+
18860
+ colPos += width;
18861
+ }
18862
+ });
18863
+
18371
18864
  this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
18372
18865
  this.tableElement.style.paddingRight = this.vDomPadRight + "px";
18373
-
18866
+
18374
18867
  this.initialized = true;
18375
-
18868
+
18376
18869
  if(!blockRedraw){
18377
18870
  if(!update || this.reinitChanged(old)){
18378
- this.renitializeRows();
18871
+ this.reinitializeRows();
18379
18872
  }
18380
18873
  }
18381
-
18874
+
18382
18875
  this.elementVertical.scrollLeft = this.scrollLeft;
18383
18876
  }
18384
-
18877
+
18385
18878
  renderRowCells(row){
18386
18879
  if(this.initialized){
18387
18880
  this.initializeRow(row);
@@ -18392,88 +18885,88 @@ class VirtualDomHorizontal extends Renderer{
18392
18885
  });
18393
18886
  }
18394
18887
  }
18395
-
18888
+
18396
18889
  rerenderRowCells(row, force){
18397
18890
  this.reinitializeRow(row, force);
18398
18891
  }
18399
-
18892
+
18400
18893
  reinitializeColumnWidths(columns){
18401
18894
  for(let i = this.leftCol; i <= this.rightCol; i++){
18402
18895
  this.columns[i].reinitializeWidth();
18403
18896
  }
18404
18897
  }
18405
-
18898
+
18406
18899
  //////////////////////////////////////
18407
18900
  //////// Internal Rendering //////////
18408
18901
  //////////////////////////////////////
18409
-
18902
+
18410
18903
  deinitialize(){
18411
18904
  this.initialized = false;
18412
18905
  }
18413
-
18906
+
18414
18907
  clear(){
18415
18908
  this.columns = [];
18416
-
18909
+
18417
18910
  this.leftCol = -1;
18418
18911
  this.rightCol = 0;
18419
-
18912
+
18420
18913
  this.vDomScrollPosLeft = 0;
18421
18914
  this.vDomScrollPosRight = 0;
18422
18915
  this.vDomPadLeft = 0;
18423
18916
  this.vDomPadRight = 0;
18424
18917
  }
18425
-
18918
+
18426
18919
  dataChange(){
18427
18920
  var change = false,
18428
18921
  collsWidth = 0,
18429
18922
  colEnd = 0,
18430
18923
  row, rowEl;
18431
-
18924
+
18432
18925
  if(this.options("layout") === "fitData"){
18433
18926
  this.table.columnManager.columnsByIndex.forEach((column) => {
18434
18927
  if(!column.definition.width && column.visible){
18435
18928
  change = true;
18436
18929
  }
18437
18930
  });
18438
-
18931
+
18439
18932
  if(change){
18440
18933
  if(change && this.table.rowManager.getDisplayRows().length){
18441
-
18934
+
18442
18935
  this.vDomScrollPosRight = this.scrollLeft + this.elementVertical.clientWidth + this.window;
18443
-
18936
+
18444
18937
  var row = this.chain("rows-sample", [1], [], () => {
18445
18938
  return this.table.rowManager.getDisplayRows()[0];
18446
18939
  })[0];
18447
-
18940
+
18448
18941
  if(row){
18449
-
18942
+
18450
18943
  rowEl = row.getElement();
18451
-
18944
+
18452
18945
  row.generateCells();
18453
-
18946
+
18454
18947
  this.tableElement.appendChild(rowEl);
18455
-
18948
+
18456
18949
  for(var colEnd = 0; colEnd < row.cells.length; colEnd++){
18457
18950
  let cell = row.cells[colEnd];
18458
18951
  rowEl.appendChild(cell.getElement());
18459
-
18952
+
18460
18953
  cell.column.reinitializeWidth();
18461
-
18954
+
18462
18955
  collsWidth += cell.column.getWidth();
18463
-
18956
+
18464
18957
  if(collsWidth > this.vDomScrollPosRight){
18465
18958
  break;
18466
18959
  }
18467
18960
  }
18468
-
18961
+
18469
18962
  rowEl.parentNode.removeChild(rowEl);
18470
-
18963
+
18471
18964
  this.fitDataColAvg = Math.floor(collsWidth / (colEnd + 1));
18472
-
18965
+
18473
18966
  for(colEnd; colEnd < this.table.columnManager.columnsByIndex.length; colEnd++){
18474
18967
  this.table.columnManager.columnsByIndex[colEnd].setWidth(this.fitDataColAvg);
18475
18968
  }
18476
-
18969
+
18477
18970
  this.rerenderColumns(false, true);
18478
18971
  }
18479
18972
  }
@@ -18485,34 +18978,34 @@ class VirtualDomHorizontal extends Renderer{
18485
18978
  }
18486
18979
  }
18487
18980
  }
18488
-
18981
+
18489
18982
  reinitChanged(old){
18490
18983
  var match = true;
18491
-
18984
+
18492
18985
  if(old.cols.length !== this.columns.length || old.leftCol !== this.leftCol || old.rightCol !== this.rightCol){
18493
18986
  return true;
18494
18987
  }
18495
-
18988
+
18496
18989
  old.cols.forEach((col, i) => {
18497
18990
  if(col !== this.columns[i]){
18498
18991
  match = false;
18499
18992
  }
18500
18993
  });
18501
-
18994
+
18502
18995
  return !match;
18503
18996
  }
18504
-
18505
- renitializeRows(){
18997
+
18998
+ reinitializeRows(){
18506
18999
  var rows = this.table.rowManager.getVisibleRows();
18507
19000
  rows.forEach((row) => {
18508
19001
  this.reinitializeRow(row, true);
18509
19002
  });
18510
19003
  }
18511
-
19004
+
18512
19005
  scroll(diff){
18513
19006
  this.vDomScrollPosLeft += diff;
18514
19007
  this.vDomScrollPosRight += diff;
18515
-
19008
+
18516
19009
  if(diff > (this.elementVertical.clientWidth * .8)){
18517
19010
  this.rerenderColumns();
18518
19011
  }else {
@@ -18527,24 +19020,23 @@ class VirtualDomHorizontal extends Renderer{
18527
19020
  }
18528
19021
  }
18529
19022
  }
18530
-
19023
+
18531
19024
  colPositionAdjust (start, end, diff){
18532
19025
  for(let i = start; i < end; i++){
18533
19026
  let column = this.columns[i];
18534
-
19027
+
18535
19028
  column.modules.vdomHoz.leftPos += diff;
18536
19029
  column.modules.vdomHoz.rightPos += diff;
18537
19030
  }
18538
19031
  }
18539
-
19032
+
18540
19033
  addColRight(){
18541
19034
  var column = this.columns[this.rightCol + 1],
18542
19035
  rows;
18543
-
19036
+
18544
19037
  if(column && column.modules.vdomHoz.leftPos <= this.vDomScrollPosRight){
18545
-
18546
19038
  rows = this.table.rowManager.getVisibleRows();
18547
-
19039
+
18548
19040
  rows.forEach((row) => {
18549
19041
  if(row.type !== "group"){
18550
19042
  var cell = row.getCell(column);
@@ -18552,30 +19044,30 @@ class VirtualDomHorizontal extends Renderer{
18552
19044
  cell.cellRendered();
18553
19045
  }
18554
19046
  });
18555
-
19047
+
18556
19048
  this.fitDataColActualWidthCheck(column);
18557
-
18558
- this.rightCol++;
18559
-
19049
+
19050
+ this.rightCol++; // Don't move this below the >= check below
19051
+
18560
19052
  if(this.rightCol >= (this.columns.length - 1)){
18561
19053
  this.vDomPadRight = 0;
18562
19054
  }else {
18563
19055
  this.vDomPadRight -= column.getWidth();
18564
19056
  }
18565
-
19057
+
18566
19058
  this.tableElement.style.paddingRight = this.vDomPadRight + "px";
18567
-
19059
+
18568
19060
  this.addColRight();
18569
19061
  }
18570
19062
  }
18571
-
19063
+
18572
19064
  addColLeft(){
18573
19065
  var column = this.columns[this.leftCol - 1],
18574
19066
  rows;
18575
-
19067
+
18576
19068
  if(column && column.modules.vdomHoz.rightPos >= this.vDomScrollPosLeft){
18577
19069
  var rows = this.table.rowManager.getVisibleRows();
18578
-
19070
+
18579
19071
  rows.forEach((row) => {
18580
19072
  if(row.type !== "group"){
18581
19073
  var cell = row.getCell(column);
@@ -18583,119 +19075,134 @@ class VirtualDomHorizontal extends Renderer{
18583
19075
  cell.cellRendered();
18584
19076
  }
18585
19077
  });
18586
-
19078
+
18587
19079
  this.fitDataColActualWidthCheck(column);
19080
+
19081
+ this.leftCol--; // don't move this below the <= check below
18588
19082
 
18589
- if(!this.leftCol){
19083
+ if(this.leftCol <= 0){ // replicating logic in addColRight
18590
19084
  this.vDomPadLeft = 0;
18591
19085
  }else {
18592
19086
  this.vDomPadLeft -= column.getWidth();
18593
19087
  }
18594
-
19088
+
18595
19089
  this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
18596
-
18597
- this.leftCol--;
18598
-
19090
+
19091
+
18599
19092
  this.addColLeft();
18600
19093
  }
18601
19094
  }
18602
-
19095
+
18603
19096
  removeColRight(column){
18604
19097
  var column = this.columns[this.rightCol],
18605
19098
  rows;
18606
-
19099
+
18607
19100
  if(column && column.modules.vdomHoz.leftPos > this.vDomScrollPosRight){
18608
19101
  rows = this.table.rowManager.getVisibleRows();
18609
-
19102
+
18610
19103
  column.modules.vdomHoz.visible = false;
18611
-
19104
+
18612
19105
  rows.forEach((row) => {
18613
19106
  if(row.type !== "group"){
18614
19107
  var cell = row.getCell(column);
18615
- row.getElement().removeChild(cell.getElement());
19108
+ try {
19109
+ row.getElement().removeChild(cell.getElement());
19110
+ } catch (ex) {
19111
+ console.warn("Could not removeColRight", ex.message);
19112
+ }
18616
19113
  }
18617
19114
  });
18618
-
19115
+
18619
19116
  this.vDomPadRight += column.getWidth();
18620
19117
  this.tableElement.style.paddingRight = this.vDomPadRight + "px";
18621
-
19118
+
18622
19119
  this.rightCol --;
18623
-
19120
+
18624
19121
  this.removeColRight();
18625
19122
  }
18626
19123
  }
18627
-
19124
+
18628
19125
  removeColLeft(){
18629
19126
  var column = this.columns[this.leftCol],
18630
19127
  rows;
18631
-
18632
- if(column && column.modules.vdomHoz.rightPos < this.vDomScrollPosLeft){
18633
-
19128
+
19129
+ if(column && column.modules.vdomHoz.rightPos < this.vDomScrollPosLeft){
18634
19130
  rows = this.table.rowManager.getVisibleRows();
18635
-
19131
+
18636
19132
  rows.forEach((row) => {
19133
+ var cell, el;
19134
+
18637
19135
  if(row.type !== "group"){
18638
- var cell = row.getCell(column);
18639
- if(cell.parentNode){
18640
- row.getElement().removeChild(cell.getElement());
19136
+ cell = row.getCell(column);
19137
+
19138
+ if(cell){
19139
+ el = cell.getElement();
19140
+
19141
+ if(el.parentNode){
19142
+ try {
19143
+ row.getElement().removeChild(el);
19144
+ } catch (ex) {
19145
+ console.warn("Could not removeColLeft", ex.message);
19146
+ }
19147
+ }
18641
19148
  }
18642
19149
  }
18643
19150
  });
18644
-
19151
+
18645
19152
  this.vDomPadLeft += column.getWidth();
18646
19153
  this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
18647
-
19154
+
18648
19155
  this.leftCol ++;
18649
-
19156
+
18650
19157
  this.removeColLeft();
18651
19158
  }
18652
19159
  }
18653
-
19160
+
18654
19161
  fitDataColActualWidthCheck(column){
18655
19162
  var newWidth, widthDiff;
18656
-
19163
+
18657
19164
  if(column.modules.vdomHoz.fitDataCheck){
18658
19165
  column.reinitializeWidth();
18659
-
19166
+
18660
19167
  newWidth = column.getWidth();
18661
19168
  widthDiff = newWidth - column.modules.vdomHoz.width;
18662
-
19169
+
18663
19170
  if(widthDiff){
18664
19171
  column.modules.vdomHoz.rightPos += widthDiff;
18665
19172
  column.modules.vdomHoz.width = newWidth;
18666
19173
  this.colPositionAdjust(this.rightCol + 2, this.columns.length, widthDiff);
18667
19174
  }
18668
-
19175
+
18669
19176
  column.modules.vdomHoz.fitDataCheck = false;
18670
19177
  }
18671
19178
  };
18672
-
19179
+
18673
19180
  initializeRow(row){
18674
19181
  if(row.type !== "group"){
18675
19182
  row.modules.vdomHoz = {
18676
19183
  leftCol:this.leftCol,
18677
19184
  rightCol:this.rightCol,
18678
19185
  };
18679
-
19186
+
18680
19187
  for(let i = this.leftCol; i <= this.rightCol; i++){
18681
19188
  let column = this.columns[i];
18682
-
19189
+
18683
19190
  if(column && column.visible){
18684
19191
  let cell = row.getCell(column);
18685
-
19192
+
18686
19193
  row.getElement().appendChild(cell.getElement());
18687
19194
  cell.cellRendered();
18688
19195
  }
18689
19196
  }
18690
19197
  }
18691
19198
  }
18692
-
19199
+
18693
19200
  reinitializeRow(row, force){
18694
19201
  if(row.type !== "group"){
18695
19202
  if(force || !row.modules.vdomHoz || row.modules.vdomHoz.leftCol !== this.leftCol || row.modules.vdomHoz.rightCol !== this.rightCol){
18696
19203
  var rowEl = row.getElement();
18697
19204
  while(rowEl.firstChild) rowEl.removeChild(rowEl.firstChild);
18698
-
19205
+
18699
19206
  this.initializeRow(row);
18700
19207
  }
18701
19208
  }
@@ -18714,7 +19221,7 @@ class ColumnManager extends CoreFeature {
18714
19221
  this.columnsByIndex = []; //columns by index
18715
19222
  this.columnsByField = {}; //columns by field
18716
19223
  this.scrollLeft = 0;
18717
- this.optionsList = new OptionsList(this.table, "column definition");
19224
+ this.optionsList = new OptionsList(this.table, "column definition", defaultColumnOptions);
18718
19225
 
18719
19226
  this.renderer = null;
18720
19227
  }
@@ -19043,7 +19550,7 @@ class ColumnManager extends CoreFeature {
19043
19550
  return this.columnsByIndex[index];
19044
19551
  }
19045
19552
 
19046
- getFirstVisibileColumn(index){
19553
+ getFirstVisibleColumn(index){
19047
19554
  var index = this.columnsByIndex.findIndex((col) => {
19048
19555
  return col.visible;
19049
19556
  });
@@ -19419,7 +19926,8 @@ class BaiscVertical extends Renderer{
19419
19926
 
19420
19927
 
19421
19928
  rerenderRows(callback){
19422
- this.render();
19929
+ this.clearRows();
19930
+ this.renderRows();
19423
19931
 
19424
19932
  if(callback){
19425
19933
  callback();
@@ -19487,7 +19995,7 @@ class VirtualDomVertical extends Renderer{
19487
19995
 
19488
19996
  element.style.paddingTop = "";
19489
19997
  element.style.paddingBottom = "";
19490
- element.style.minWidth = "";
19998
+ // element.style.minWidth = "";
19491
19999
  element.style.minHeight = "";
19492
20000
  element.style.display = "";
19493
20001
  element.style.visibility = "";
@@ -20027,7 +20535,7 @@ class RowManager extends CoreFeature{
20027
20535
  this.fixedHeight = false; //current rendering mode
20028
20536
 
20029
20537
  this.rows = []; //hold row data objects
20030
- this.activeRowsPipeline = []; //hold caluclation of active rows
20538
+ this.activeRowsPipeline = []; //hold calculation of active rows
20031
20539
  this.activeRows = []; //rows currently available to on display in the table
20032
20540
  this.activeRowsCount = 0; //count of active rows
20033
20541
 
@@ -20039,9 +20547,9 @@ class RowManager extends CoreFeature{
20039
20547
 
20040
20548
  this.rowNumColumn = false; //hold column component for row number column
20041
20549
 
20042
- this.redrawBlock = false; //prevent redraws to allow multiple data manipulations becore continuing
20550
+ this.redrawBlock = false; //prevent redraws to allow multiple data manipulations before continuing
20043
20551
  this.redrawBlockRestoreConfig = false; //store latest redraw function calls for when redraw is needed
20044
- this.redrawBlockRederInPosition = false; //store latest redraw function calls for when redraw is needed
20552
+ this.redrawBlockRenderInPosition = false; //store latest redraw function calls for when redraw is needed
20045
20553
 
20046
20554
  this.dataPipeline = []; //hold data pipeline tasks
20047
20555
  this.displayPipeline = []; //hold data display pipeline tasks
@@ -20712,7 +21220,7 @@ class RowManager extends CoreFeature{
20712
21220
  }
20713
21221
  }
20714
21222
 
20715
- this.dispatch("data-refeshed");
21223
+ this.dispatch("data-refreshed");
20716
21224
  }
20717
21225
  }
20718
21226
 
@@ -20775,8 +21283,14 @@ class RowManager extends CoreFeature{
20775
21283
  }
20776
21284
  }
20777
21285
 
20778
- getVisibleRows(viewable){
20779
- return this.renderer.visibleRows(!viewable);
21286
+ getVisibleRows(chain, viewable){
21287
+ var rows = Object.assign([], this.renderer.visibleRows(!viewable));
21288
+
21289
+ if(chain){
21290
+ rows = this.chain("rows-visible", [viewable], rows, rows);
21291
+ }
21292
+
21293
+ return rows;
20780
21294
  }
20781
21295
 
20782
21296
  //repeat action accross display rows
@@ -20818,7 +21332,7 @@ class RowManager extends CoreFeature{
20818
21332
  if(callback){
20819
21333
  callback();
20820
21334
  }else {
20821
- this.redrawBlockRederInPosition = true;
21335
+ this.redrawBlockRenderInPosition = true;
20822
21336
  }
20823
21337
  }else {
20824
21338
  this.renderer.rerenderRows(callback);
@@ -20997,12 +21511,12 @@ class RowManager extends CoreFeature{
20997
21511
 
20998
21512
  this.redrawBlockRestoreConfig = false;
20999
21513
  }else {
21000
- if(this.redrawBlockRederInPosition){
21514
+ if(this.redrawBlockRenderInPosition){
21001
21515
  this.reRenderInPosition();
21002
21516
  }
21003
21517
  }
21004
21518
 
21005
- this.redrawBlockRederInPosition = false;
21519
+ this.redrawBlockRenderInPosition = false;
21006
21520
  }
21007
21521
 
21008
21522
  //redraw table
@@ -21140,29 +21654,29 @@ class FooterManager extends CoreFeature{
21140
21654
  }
21141
21655
 
21142
21656
  class InteractionManager extends CoreFeature {
21143
-
21657
+
21144
21658
  constructor (table){
21145
21659
  super(table);
21146
-
21147
- this.el = this.table.element;
21148
-
21660
+
21661
+ this.el = null;
21662
+
21149
21663
  this.abortClasses = ["tabulator-headers", "tabulator-table"];
21150
-
21664
+
21151
21665
  this.previousTargets = {};
21152
-
21666
+
21153
21667
  this.listeners = [
21154
- "click",
21155
- "dblclick",
21156
- "contextmenu",
21157
- "mouseenter",
21158
- "mouseleave",
21159
- "mouseover",
21160
- "mouseout",
21161
- "mousemove",
21162
- "touchstart",
21163
- "touchend",
21668
+ "click",
21669
+ "dblclick",
21670
+ "contextmenu",
21671
+ "mouseenter",
21672
+ "mouseleave",
21673
+ "mouseover",
21674
+ "mouseout",
21675
+ "mousemove",
21676
+ "touchstart",
21677
+ "touchend",
21164
21678
  ];
21165
-
21679
+
21166
21680
  this.componentMap = {
21167
21681
  "tabulator-cell":"cell",
21168
21682
  "tabulator-row":"row",
@@ -21170,36 +21684,111 @@ class InteractionManager extends CoreFeature {
21170
21684
  "tabulator-col":"column",
21171
21685
  };
21172
21686
 
21687
+ this.pseudoTrackers = {
21688
+ "row":{
21689
+ subscriber:null,
21690
+ target:null,
21691
+ },
21692
+ "cell":{
21693
+ subscriber:null,
21694
+ target:null,
21695
+ },
21696
+ "group":{
21697
+ subscriber:null,
21698
+ target:null,
21699
+ },
21700
+ "column":{
21701
+ subscriber:null,
21702
+ target:null,
21703
+ },
21704
+ };
21705
+
21706
+ this.pseudoTracking = false;
21707
+ }
21708
+
21709
+ initialize(){
21710
+ this.el = this.table.element;
21173
21711
  this.buildListenerMap();
21174
21712
  this.bindSubscriptionWatchers();
21175
21713
  }
21176
-
21714
+
21177
21715
  buildListenerMap(){
21178
21716
  var listenerMap = {};
21179
-
21717
+
21180
21718
  this.listeners.forEach((listener) => {
21181
21719
  listenerMap[listener] = {
21182
21720
  handler:null,
21183
21721
  components:[],
21184
21722
  };
21185
21723
  });
21186
-
21724
+
21187
21725
  this.listeners = listenerMap;
21188
21726
  }
21189
21727
 
21728
+ bindPseudoEvents(){
21729
+ Object.keys(this.pseudoTrackers).forEach((key) => {
21730
+ this.pseudoTrackers[key].subscriber = this.pseudoMouseEnter.bind(this, key);
21731
+ this.subscribe(key + "-mouseover", this.pseudoTrackers[key].subscriber);
21732
+ });
21733
+
21734
+ this.pseudoTracking = true;
21735
+ }
21736
+
21737
+ pseudoMouseEnter(key, e, target){
21738
+ if(this.pseudoTrackers[key].target !== target){
21739
+
21740
+ if(this.pseudoTrackers[key].target){
21741
+ this.dispatch(key + "-mouseleave", e, target);
21742
+ }
21743
+
21744
+ this.pseudoMouseLeave(key, e);
21745
+
21746
+ this.pseudoTrackers[key].target = target;
21747
+
21748
+ this.dispatch(key + "-mouseenter", e, target);
21749
+ }
21750
+ }
21751
+
21752
+ pseudoMouseLeave(key, e){
21753
+ var leaveList = Object.keys(this.pseudoTrackers),
21754
+ linkedKeys = {
21755
+ "row":["cell"],
21756
+ "cell":["row"],
21757
+ };
21758
+
21759
+ leaveList = leaveList.filter((item) => {
21760
+ var links = linkedKeys[key];
21761
+ return item !== key && (!links || (links && !links.includes(item)));
21762
+ });
21763
+
21764
+
21765
+ leaveList.forEach((key) => {
21766
+ var target = this.pseudoTrackers[key].target;
21767
+
21768
+ if(this.pseudoTrackers[key].target){
21769
+ this.dispatch(key + "-mouseleave", e, target);
21770
+
21771
+ this.pseudoTrackers[key].target = null;
21772
+ }
21773
+ });
21774
+ }
21775
+
21776
+
21190
21777
  bindSubscriptionWatchers(){
21191
21778
  var listeners = Object.keys(this.listeners),
21192
21779
  components = Object.values(this.componentMap);
21193
-
21780
+
21194
21781
  for(let comp of components){
21195
21782
  for(let listener of listeners){
21196
21783
  let key = comp + "-" + listener;
21197
-
21784
+
21198
21785
  this.subscriptionChange(key, this.subscriptionChanged.bind(this, comp, listener));
21199
21786
  }
21200
21787
  }
21788
+
21789
+ this.subscribe("table-destroy", this.clearWatchers.bind(this));
21201
21790
  }
21202
-
21791
+
21203
21792
  subscriptionChanged(component, key, added){
21204
21793
  var listener = this.listeners[key].components,
21205
21794
  index = listener.indexOf(component),
@@ -21219,15 +21808,19 @@ class InteractionManager extends CoreFeature {
21219
21808
  }
21220
21809
  }
21221
21810
 
21811
+ if((key === "mouseenter" || key === "mouseleave") && !this.pseudoTracking){
21812
+ this.bindPseudoEvents();
21813
+ }
21814
+
21222
21815
  if(changed){
21223
21816
  this.updateEventListeners();
21224
21817
  }
21225
21818
  }
21226
-
21819
+
21227
21820
  updateEventListeners(){
21228
21821
  for(let key in this.listeners){
21229
21822
  let listener = this.listeners[key];
21230
-
21823
+
21231
21824
  if(listener.components.length){
21232
21825
  if(!listener.handler){
21233
21826
  listener.handler = this.track.bind(this, key);
@@ -21242,86 +21835,96 @@ class InteractionManager extends CoreFeature {
21242
21835
  }
21243
21836
  }
21244
21837
  }
21245
-
21838
+
21246
21839
  track(type, e){
21247
21840
  var path = (e.composedPath && e.composedPath()) || e.path;
21841
+
21248
21842
  var targets = this.findTargets(path);
21249
21843
  targets = this.bindComponents(type, targets);
21844
+
21250
21845
  this.triggerEvents(type, e, targets);
21251
- }
21252
21846
 
21847
+ if(this.pseudoTracking && (type == "mouseover" || type == "mouseleave") && !Object.keys(targets).length){
21848
+ this.pseudoMouseLeave("none", e);
21849
+ }
21850
+ }
21851
+
21253
21852
  findTargets(path){
21254
21853
  var targets = {};
21255
-
21854
+
21256
21855
  let componentMap = Object.keys(this.componentMap);
21257
-
21856
+
21258
21857
  for (let el of path) {
21259
21858
  let classList = el.classList ? [...el.classList] : [];
21260
-
21859
+
21261
21860
  let abort = classList.filter((item) => {
21262
21861
  return this.abortClasses.includes(item);
21263
21862
  });
21264
-
21863
+
21265
21864
  if(abort.length){
21266
21865
  break;
21267
21866
  }
21268
-
21867
+
21269
21868
  let elTargets = classList.filter((item) => {
21270
21869
  return componentMap.includes(item);
21271
21870
  });
21272
-
21871
+
21273
21872
  for (let target of elTargets) {
21274
21873
  targets[this.componentMap[target]] = el;
21275
21874
  }
21276
21875
  }
21277
-
21876
+
21278
21877
  if(targets.group && targets.group === targets.row){
21279
21878
  delete targets.row;
21280
21879
  }
21281
-
21880
+
21282
21881
  return targets;
21283
21882
  }
21284
-
21883
+
21285
21884
  bindComponents(type, targets){
21286
21885
  //ensure row component is looked up before cell
21287
21886
  var keys = Object.keys(targets).reverse(),
21288
21887
  listener = this.listeners[type],
21289
21888
  targetMatches = {};
21290
-
21889
+
21291
21890
  for(let key of keys){
21292
21891
  let component;
21293
21892
  let target = targets[key];
21294
21893
  let previousTarget = this.previousTargets[key];
21295
-
21894
+
21296
21895
  if(previousTarget && previousTarget.target === target){
21297
21896
  component = previousTarget.component;
21298
21897
  }else {
21299
21898
  switch(key){
21300
21899
  case "row":
21301
21900
  case "group":
21302
- if(listener.components.includes("row") || listener.components.includes("cell")){
21303
- let rows = this.table.rowManager.getVisibleRows();
21304
-
21901
+ if(listener.components.includes("row") || listener.components.includes("cell") || listener.components.includes("group")){
21902
+ let rows = this.table.rowManager.getVisibleRows(true);
21903
+
21305
21904
  component = rows.find((row) => {
21306
21905
  return row.getElement() === target;
21307
21906
  });
21308
21907
  }
21309
21908
  break;
21310
-
21909
+
21311
21910
  case "column":
21312
21911
  if(listener.components.includes("column")){
21313
21912
  component = this.table.columnManager.findColumn(target);
21314
21913
  }
21315
21914
  break
21316
-
21915
+
21317
21916
  case "cell":
21318
21917
  if(listener.components.includes("cell")){
21319
- component = targets["row"].findCell(target);
21918
+ if(targets["row"]){
21919
+ component = targets["row"].findCell(target);
21920
+ }else {
21921
+ console.warn("Event Target Lookup Error - The row this cell is attached to cannot be found, has the table been reinitialized without being destroyed first?");
21922
+ }
21320
21923
  }
21321
21924
  break;
21322
21925
  }
21323
21926
  }
21324
-
21927
+
21325
21928
  if(component){
21326
21929
  targets[key] = component;
21327
21930
  targetMatches[key] = {
@@ -21330,24 +21933,35 @@ class InteractionManager extends CoreFeature {
21330
21933
  };
21331
21934
  }
21332
21935
  }
21333
-
21936
+
21334
21937
  this.previousTargets = targetMatches;
21335
-
21938
+
21336
21939
  return targets;
21337
21940
  }
21338
-
21941
+
21339
21942
  triggerEvents(type, e, targets){
21340
21943
  var listener = this.listeners[type];
21341
-
21944
+
21342
21945
  for(let key in targets){
21343
21946
  if(targets[key] && listener.components.includes(key)){
21344
21947
  this.dispatch(key + "-" + type, e, targets[key]);
21345
21948
  }
21346
21949
  }
21347
21950
  }
21951
+
21952
+ clearWatchers(){
21953
+ for(let key in this.listeners){
21954
+ let listener = this.listeners[key];
21955
+
21956
+ if(listener.handler){
21957
+ this.el.removeEventListener(key, listener.handler);
21958
+ listener.handler = null;
21959
+ }
21960
+ }
21961
+ }
21348
21962
  }
21349
21963
 
21350
- class ComponentFuctionBinder{
21964
+ class ComponentFunctionBinder{
21351
21965
 
21352
21966
  constructor(table){
21353
21967
  this.table = table;
@@ -21442,7 +22056,7 @@ class DataLoader extends CoreFeature{
21442
22056
  data = JSON.parse(data);
21443
22057
  }
21444
22058
 
21445
- if(this.confirm("data-loading", data, params, config, silent)){
22059
+ if(this.confirm("data-loading", [data, params, config, silent])){
21446
22060
  this.loading = true;
21447
22061
 
21448
22062
  if(!silent){
@@ -21450,12 +22064,12 @@ class DataLoader extends CoreFeature{
21450
22064
  }
21451
22065
 
21452
22066
  //get params for request
21453
- var params = this.chain("data-params", [data, config, silent], params || {}, {});
22067
+ params = this.chain("data-params", [data, config, silent], params || {}, params || {});
21454
22068
 
21455
22069
  params = this.mapParams(params, this.table.options.dataSendParams);
21456
22070
 
21457
- var result = this.chain("data-load", [data, params, config, silent], Promise.resolve([]));
21458
-
22071
+ var result = this.chain("data-load", [data, params, config, silent], false, Promise.resolve([]));
22072
+
21459
22073
  return result.then((response) => {
21460
22074
  if(!Array.isArray(response) && typeof response == "object"){
21461
22075
  response = this.mapParams(response, this.objectInvert(this.table.options.dataReceiveParams));
@@ -21480,10 +22094,10 @@ class DataLoader extends CoreFeature{
21480
22094
  if(!silent){
21481
22095
  this.showError();
21482
22096
  }
21483
-
22097
+
21484
22098
  setTimeout(() => {
21485
22099
  this.hideLoader();
21486
- }, 3000);
22100
+ }, this.table.options.dataLoaderErrorTimeout);
21487
22101
  })
21488
22102
  .finally(() => {
21489
22103
  this.loading = false;
@@ -22210,6 +22824,12 @@ var defaultLangs = {
22210
22824
  "next":"Next",
22211
22825
  "next_title":"Next Page",
22212
22826
  "all":"All",
22827
+ "counter":{
22828
+ "showing": "Showing",
22829
+ "of": "of",
22830
+ "rows": "rows",
22831
+ "pages": "pages",
22832
+ }
22213
22833
  },
22214
22834
  "headerFilters":{
22215
22835
  "default":"filter column...",
@@ -22560,11 +23180,11 @@ class Tabulator {
22560
23180
  this.interactionMonitor = false; //track user interaction
22561
23181
  this.browser = ""; //hold current browser type
22562
23182
  this.browserSlow = false; //handle reduced functionality for slower browsers
22563
- this.browserMobile = false; //check if running on moble, prevent resize cancelling edit on keyboard appearence
23183
+ this.browserMobile = false; //check if running on mobile, prevent resize cancelling edit on keyboard appearance
22564
23184
  this.rtl = false; //check if the table is in RTL mode
22565
23185
  this.originalElement = null; //hold original table element if it has been replaced
22566
23186
 
22567
- this.componentFunctionBinder = new ComponentFuctionBinder(this); //bind component functions
23187
+ this.componentFunctionBinder = new ComponentFunctionBinder(this); //bind component functions
22568
23188
  this.dataLoader = false; //bind component functions
22569
23189
 
22570
23190
  this.modules = {}; //hold all modules bound to this table
@@ -22579,13 +23199,13 @@ class Tabulator {
22579
23199
 
22580
23200
  this.initialzeCoreSystems(options);
22581
23201
 
22582
- //delay table creation to allow event bindings immediatly after the constructor
23202
+ //delay table creation to allow event bindings immediately after the constructor
22583
23203
  setTimeout(() => {
22584
23204
  this._create();
22585
23205
  });
22586
23206
  }
22587
23207
 
22588
- TableRegistry.register(this); //register table for inderdevice communication
23208
+ TableRegistry.register(this); //register table for inter-device communication
22589
23209
  }
22590
23210
 
22591
23211
  initializeElement(element){
@@ -22619,7 +23239,7 @@ class Tabulator {
22619
23239
 
22620
23240
  this._clearObjectPointers();
22621
23241
 
22622
- this._mapDepricatedFunctionality();
23242
+ this._mapDeprecatedFunctionality();
22623
23243
 
22624
23244
  this.externalEvents = new ExternalEventBus(this, this.options, this.options.debugEventsExternal);
22625
23245
  this.eventBus = new InternalEventBus(this.options.debugEventsInternal);
@@ -22632,8 +23252,8 @@ class Tabulator {
22632
23252
  this.footerManager.initialize();
22633
23253
  }
22634
23254
 
22635
- //convert depricated functionality to new functions
22636
- _mapDepricatedFunctionality(){
23255
+ //convert deprecated functionality to new functions
23256
+ _mapDeprecatedFunctionality(){
22637
23257
  //all previously deprecated functionality removed in the 5.0 release
22638
23258
  }
22639
23259
 
@@ -22654,7 +23274,7 @@ class Tabulator {
22654
23274
  this.element.classList.remove("tabulator-block-select");
22655
23275
  }
22656
23276
 
22657
- //concreate table
23277
+ //create table
22658
23278
  _create(){
22659
23279
  this.externalEvents.dispatch("tableBuilding");
22660
23280
  this.eventBus.dispatch("table-building");
@@ -22758,6 +23378,8 @@ class Tabulator {
22758
23378
  var element = this.element,
22759
23379
  options = this.options;
22760
23380
 
23381
+ this.interactionMonitor.initialize();
23382
+
22761
23383
  this.columnManager.initialize();
22762
23384
  this.rowManager.initialize();
22763
23385
 
@@ -22816,7 +23438,7 @@ class Tabulator {
22816
23438
  destroy(){
22817
23439
  var element = this.element;
22818
23440
 
22819
- TableRegistry.deregister(this); //deregister table from inderdevice communication
23441
+ TableRegistry.deregister(this); //deregister table from inter-device communication
22820
23442
 
22821
23443
  this.eventBus.dispatch("table-destroy");
22822
23444
 
@@ -22865,49 +23487,6 @@ class Tabulator {
22865
23487
  return this.rowManager.restoreRedraw();
22866
23488
  }
22867
23489
 
22868
- //local data from local file
22869
- setDataFromLocalFile(extensions){
22870
- return new Promise((resolve, reject) => {
22871
- var input = document.createElement("input");
22872
- input.type = "file";
22873
- input.accept = extensions || ".json,application/json";
22874
-
22875
- input.addEventListener("change", (e) => {
22876
- var file = input.files[0],
22877
- reader = new FileReader(),
22878
- data;
22879
-
22880
- reader.readAsText(file);
22881
-
22882
- reader.onload = (e) => {
22883
-
22884
- try {
22885
- data = JSON.parse(reader.result);
22886
- } catch(e) {
22887
- console.warn("File Load Error - File contents is invalid JSON", e);
22888
- reject(e);
22889
- return;
22890
- }
22891
-
22892
- this.setData(data)
22893
- .then((data) => {
22894
- resolve(data);
22895
- })
22896
- .catch((err) => {
22897
- resolve(err);
22898
- });
22899
- };
22900
-
22901
- reader.onerror = (e) => {
22902
- console.warn("File Load Error - Unable to read file");
22903
- reject();
22904
- };
22905
- });
22906
-
22907
- input.click();
22908
- });
22909
- }
22910
-
22911
23490
  //load data
22912
23491
  setData(data, params, config){
22913
23492
  if(this.initialized){
@@ -23169,7 +23748,7 @@ class Tabulator {
23169
23748
  if(row){
23170
23749
  return row.updateData(data)
23171
23750
  .then(()=>{
23172
- resolve(row.getComponent());
23751
+ return Promise.resolve(row.getComponent());
23173
23752
  })
23174
23753
  }else {
23175
23754
  console.warn("Update Error - No matching row found:", index);
@@ -23200,11 +23779,7 @@ class Tabulator {
23200
23779
  }
23201
23780
 
23202
23781
  getRows(active){
23203
- if(this.initialized){
23204
- return this.rowManager.getComponents(active);
23205
- }else {
23206
- console.warn("getRows failed - table not yet initialized. Please wait for the `tableBuilt` event before calling this function.");
23207
- }
23782
+ return this.rowManager.getComponents(active);
23208
23783
  }
23209
23784
 
23210
23785
  //get position of row in table
@@ -23403,7 +23978,7 @@ class Tabulator {
23403
23978
  }
23404
23979
 
23405
23980
  //default setup options
23406
- Tabulator.defaultOptions = defaultOptions$1;
23981
+ Tabulator.defaultOptions = defaultOptions;
23407
23982
 
23408
23983
  //bind modules and static functionality
23409
23984
  new ModuleBinder(Tabulator);
@@ -23460,5 +24035,5 @@ class PseudoRow {
23460
24035
  clearCellHeight(){}
23461
24036
  }
23462
24037
 
23463
- export { Accessor as AccessorModule, Ajax as AjaxModule, CalcComponent, CellComponent, Clipboard as ClipboardModule, ColumnCalcs as ColumnCalcsModule, ColumnComponent, DataTree as DataTreeModule, Download as DownloadModule, Edit as EditModule, Export as ExportModule, Filter as FilterModule, Format as FormatModule, FrozenColumns as FrozenColumnsModule, FrozenRows as FrozenRowsModule, GroupComponent, GroupRows as GroupRowsModule, History as HistoryModule, HtmlTableImport as HtmlTableImportModule, Interaction as InteractionModule, Keybindings as KeybindingsModule, Menu as MenuModule, Module, MoveColumns as MoveColumnsModule, MoveRows as MoveRowsModule, Mutator as MutatorModule, Page as PageModule, Persistence as PersistenceModule, Print as PrintModule, PseudoRow, ReactiveData as ReactiveDataModule, Renderer, ResizeColumns as ResizeColumnsModule, ResizeRows as ResizeRowsModule, ResizeTable as ResizeTableModule, ResponsiveLayout as ResponsiveLayoutModule, RowComponent$1 as RowComponent, SelectRow as SelectRowModule, Sort as SortModule, Tabulator, TabulatorFull, Validate as ValidateModule };
24038
+ export { Accessor as AccessorModule, Ajax as AjaxModule, CalcComponent, CellComponent, Clipboard as ClipboardModule, ColumnCalcs as ColumnCalcsModule, ColumnComponent, DataTree as DataTreeModule, Download as DownloadModule, Edit as EditModule, Export as ExportModule, Filter as FilterModule, Format as FormatModule, FrozenColumns as FrozenColumnsModule, FrozenRows as FrozenRowsModule, GroupComponent, GroupRows as GroupRowsModule, History as HistoryModule, HtmlTableImport as HtmlTableImportModule, Import as ImportModule, Interaction as InteractionModule, Keybindings as KeybindingsModule, Menu as MenuModule, Module, MoveColumns as MoveColumnsModule, MoveRows as MoveRowsModule, Mutator as MutatorModule, Page as PageModule, Persistence as PersistenceModule, Print as PrintModule, PseudoRow, ReactiveData as ReactiveDataModule, Renderer, ResizeColumns as ResizeColumnsModule, ResizeRows as ResizeRowsModule, ResizeTable as ResizeTableModule, ResponsiveLayout as ResponsiveLayoutModule, RowComponent$1 as RowComponent, SelectRow as SelectRowModule, Sort as SortModule, Tabulator, TabulatorFull, Validate as ValidateModule };
23464
24039
  //# sourceMappingURL=tabulator_esm.js.map