tabulator-tables 5.0.10 → 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 (100) 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 -6
  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 -6
  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 -6
  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 -6
  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 -10
  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 -6
  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 -6
  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 -6
  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 -6
  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 -6
  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 +853 -390
  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 +1106 -656
  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/RowManager.js +7 -7
  55. package/src/js/core/Tabulator.js +0 -43
  56. package/src/js/core/cell/Cell.js +5 -1
  57. package/src/js/core/column/Column.js +19 -4
  58. package/src/js/core/column/ColumnComponent.js +4 -0
  59. package/src/js/core/column/defaults/options.js +1 -0
  60. package/src/js/core/defaults/options.js +2 -2
  61. package/src/js/core/modules/optional.js +1 -0
  62. package/src/js/core/rendering/renderers/BasicVertical.js +2 -1
  63. package/src/js/core/rendering/renderers/VirtualDomHorizontal.js +17 -8
  64. package/src/js/core/row/Row.js +2 -2
  65. package/src/js/core/tools/DataLoader.js +4 -4
  66. package/src/js/core/tools/InteractionMonitor.js +6 -2
  67. package/src/js/modules/Ajax/Ajax.js +62 -82
  68. package/src/js/modules/ColumnCalcs/ColumnCalcs.js +1 -1
  69. package/src/js/modules/DataTree/DataTree.js +5 -0
  70. package/src/js/modules/Download/defaults/downloaders/json.js +1 -1
  71. package/src/js/modules/Download/defaults/downloaders/jsonLines.js +32 -0
  72. package/src/js/modules/Download/defaults/downloaders.js +2 -0
  73. package/src/js/modules/Edit/Edit.js +23 -31
  74. package/src/js/modules/Filter/Filter.js +1 -1
  75. package/src/js/modules/Format/defaults/formatters/datetime.js +1 -1
  76. package/src/js/modules/Format/defaults/formatters/datetimediff.js +2 -1
  77. package/src/js/modules/FrozenRows/FrozenRows.js +9 -0
  78. package/src/js/modules/GroupRows/Group.js +2 -61
  79. package/src/js/modules/GroupRows/GroupRows.js +2 -2
  80. package/src/js/modules/Import/Import.js +197 -0
  81. package/src/js/modules/Import/defaults/importers/csv.js +63 -0
  82. package/src/js/modules/Import/defaults/importers/json.js +8 -0
  83. package/src/js/modules/Import/defaults/importers.js +7 -0
  84. package/src/js/modules/Interaction/Interaction.js +5 -0
  85. package/src/js/modules/Keybindings/Keybindings.js +9 -14
  86. package/src/js/modules/Keybindings/defaults/bindings.js +3 -3
  87. package/src/js/modules/Localize/defaults/langs.js +6 -0
  88. package/src/js/modules/Menu/Menu.js +200 -155
  89. package/src/js/modules/MoveRows/MoveRows.js +4 -0
  90. package/src/js/modules/Page/Page.js +271 -173
  91. package/src/js/modules/Page/defaults/pageCounters/pages.js +33 -0
  92. package/src/js/modules/Page/defaults/pageCounters/rows.js +32 -0
  93. package/src/js/modules/Page/defaults/pageCounters.js +8 -0
  94. package/src/js/modules/ResizeRows/ResizeRows.js +1 -1
  95. package/src/js/modules/Sort/defaults/sorters/datetime.js +2 -2
  96. package/src/js/modules/Validate/Validate.js +7 -5
  97. package/src/scss/tabulator.scss +20 -6
  98. package/src/scss/themes/materialize/tabulator_materialize.scss +5 -4
  99. package/src/scss/themes/tabulator_midnight.scss +4 -0
  100. package/src/scss/themes/tabulator_site.scss +4 -0
@@ -1,4 +1,4 @@
1
- /* Tabulator v5.0.10 (c) Oliver Folkerd 2021 */
1
+ /* Tabulator v5.1.0 (c) Oliver Folkerd 2022 */
2
2
  class CoreFeature{
3
3
 
4
4
  constructor(table){
@@ -535,144 +535,125 @@ var defaultContentTypeFormatters = {
535
535
  };
536
536
 
537
537
  class Ajax extends Module{
538
-
538
+
539
539
  constructor(table){
540
540
  super(table);
541
-
542
- this.config = false; //hold config object for ajax request
541
+
542
+ this.config = {}; //hold config object for ajax request
543
543
  this.url = ""; //request URL
544
544
  this.urlGenerator = false;
545
545
  this.params = false; //request parameters
546
-
546
+
547
547
  this.loaderPromise = false;
548
-
548
+
549
549
  this.registerTableOption("ajaxURL", false); //url for ajax loading
550
550
  this.registerTableOption("ajaxURLGenerator", false);
551
551
  this.registerTableOption("ajaxParams", {}); //params for ajax loading
552
552
  this.registerTableOption("ajaxConfig", "get"); //ajax request type
553
553
  this.registerTableOption("ajaxContentType", "form"); //ajax request type
554
554
  this.registerTableOption("ajaxRequestFunc", false); //promise function
555
-
555
+
556
556
  this.registerTableOption("ajaxRequesting", function(){});
557
557
  this.registerTableOption("ajaxResponse", false);
558
-
558
+
559
559
  this.contentTypeFormatters = Ajax.contentTypeFormatters;
560
560
  }
561
-
561
+
562
562
  //initialize setup options
563
563
  initialize(){
564
564
  this.loaderPromise = this.table.options.ajaxRequestFunc || Ajax.defaultLoaderPromise;
565
565
  this.urlGenerator = this.table.options.ajaxURLGenerator || Ajax.defaultURLGenerator;
566
-
567
- if(this.table.options.ajaxParams){
568
- this.setParams(this.table.options.ajaxParams);
569
- }
570
-
571
- if(this.table.options.ajaxConfig){
572
- this.setConfig(this.table.options.ajaxConfig);
573
- }
574
-
566
+
575
567
  if(this.table.options.ajaxURL){
576
568
  this.setUrl(this.table.options.ajaxURL);
577
569
  }
578
570
 
579
- this.registerTableFunction("getAjaxUrl", this.getUrl.bind(this));
580
571
 
572
+ this.setDefaultConfig(this.table.options.ajaxConfig);
573
+
574
+ this.registerTableFunction("getAjaxUrl", this.getUrl.bind(this));
575
+
581
576
  this.subscribe("data-loading", this.requestDataCheck.bind(this));
577
+ this.subscribe("data-params", this.requestParams.bind(this));
582
578
  this.subscribe("data-load", this.requestData.bind(this));
583
579
  }
584
-
585
-
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
+
586
595
  requestDataCheck(data, params, config, silent){
587
596
  return !!((!data && this.url) || typeof data === "string");
588
597
  }
589
-
590
- requestData(data, params, config, silent, previousData){
591
- if(this.requestDataCheck(data)){
592
- if(data){
593
- this.setUrl(data);
594
- }
595
-
596
- if(params){
597
- this.setParams(params, true);
598
- }
599
-
600
- if(config){
601
- this.setConfig(config);
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);
602
605
  }
603
-
604
- return this.sendRequest();
606
+
607
+ ajaxConfig = this.generateConfig(config);
608
+
609
+ return this.sendRequest(this.url, params, ajaxConfig);
605
610
  }else {
606
611
  return previousData;
607
612
  }
608
613
  }
614
+
615
+ setDefaultConfig(config = {}){
616
+ this.config = Object.assign({}, Ajax.defaultConfig);
609
617
 
610
- //set ajax params
611
- setParams(params, update){
612
- if(update){
613
- this.params = this.params || {};
614
-
615
- for(let key in params){
616
- this.params[key] = params[key];
617
- }
618
+ if(typeof config == "string"){
619
+ this.config.method = config;
618
620
  }else {
619
- this.params = params;
621
+ Object.assign(this.config, config);
620
622
  }
621
623
  }
622
-
623
- getParams(){
624
- return this.params || {};
625
- }
626
-
624
+
627
625
  //load config object
628
- setConfig(config){
629
- this._loadDefaultConfig();
630
-
626
+ generateConfig(config = {}){
627
+ var ajaxConfig = Object.assign({}, this.config);
628
+
631
629
  if(typeof config == "string"){
632
- this.config.method = config;
630
+ ajaxConfig.method = config;
633
631
  }else {
634
- for(let key in config){
635
- this.config[key] = config[key];
636
- }
637
- }
638
- }
639
-
640
- //create config object from default
641
- _loadDefaultConfig(force){
642
- if(!this.config || force){
643
-
644
- this.config = {};
645
-
646
- //load base config from defaults
647
- for(let key in Ajax.defaultConfig){
648
- this.config[key] = Ajax.defaultConfig[key];
649
- }
632
+ Object.assign(ajaxConfig, config);
650
633
  }
634
+
635
+ return ajaxConfig;
651
636
  }
652
-
637
+
653
638
  //set request url
654
639
  setUrl(url){
655
640
  this.url = url;
656
641
  }
657
-
642
+
658
643
  //get request url
659
644
  getUrl(){
660
645
  return this.url;
661
646
  }
662
-
647
+
663
648
  //send ajax request
664
- sendRequest(silent){
665
- var url = this.url;
666
-
667
- this._loadDefaultConfig();
668
-
669
- if(this.table.options.ajaxRequesting.call(this.table, this.url, this.params) !== false){
670
- 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)
671
652
  .then((data)=>{
672
653
  if(this.table.options.ajaxResponse){
673
- 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);
674
655
  }
675
-
656
+
676
657
  return data;
677
658
  });
678
659
  }else {
@@ -1366,6 +1347,10 @@ class Cell extends CoreFeature{
1366
1347
 
1367
1348
  this.cellRendered();
1368
1349
 
1350
+ if(this.column.definition.cellEdited){
1351
+ this.column.definition.cellEdited.call(this.table, this.getComponent());
1352
+ }
1353
+
1369
1354
  this.dispatchExternal("cellEdited", this.getComponent());
1370
1355
 
1371
1356
  if(this.subscribedExternal("dataChanged")){
@@ -1377,7 +1362,7 @@ class Cell extends CoreFeature{
1377
1362
  setValueProcessData(value, mutate){
1378
1363
  var changed = false;
1379
1364
 
1380
- if(this.value != value){
1365
+ if(this.value !== value){
1381
1366
 
1382
1367
  changed = true;
1383
1368
 
@@ -1525,6 +1510,10 @@ class ColumnComponent {
1525
1510
  return this._column.getField();
1526
1511
  }
1527
1512
 
1513
+ getTitleDownload() {
1514
+ return this._column.getTitleDownload();
1515
+ }
1516
+
1528
1517
  getCells(){
1529
1518
  var cells = [];
1530
1519
 
@@ -1654,6 +1643,7 @@ var defaultColumnOptions = {
1654
1643
  "width": undefined,
1655
1644
  "minWidth": 40,
1656
1645
  "maxWidth": undefined,
1646
+ "maxInitialWidth": undefined,
1657
1647
  "tooltip": undefined,
1658
1648
  "cssClass": undefined,
1659
1649
  "variableHeight": undefined,
@@ -1689,6 +1679,7 @@ class Column$1 extends CoreFeature{
1689
1679
  this.getFieldValue = "";
1690
1680
  this.setFieldValue = "";
1691
1681
 
1682
+ this.titleDownload = null;
1692
1683
  this.titleFormatterRendered = false;
1693
1684
 
1694
1685
  this.mapDefinitions();
@@ -1701,6 +1692,7 @@ class Column$1 extends CoreFeature{
1701
1692
  this.widthStyled = ""; //column width prestyled to improve render efficiency
1702
1693
  this.maxWidth = null; //column maximum width
1703
1694
  this.maxWidthStyled = ""; //column maximum prestyled to improve render efficiency
1695
+ this.maxInitialWidth = null;
1704
1696
  this.minWidth = null; //column minimum width
1705
1697
  this.minWidthStyled = ""; //column minimum prestyled to improve render efficiency
1706
1698
  this.widthFixed = false; //user has specified a width for this column
@@ -1979,6 +1971,10 @@ class Column$1 extends CoreFeature{
1979
1971
  //set min width if present
1980
1972
  this.setMinWidth(parseInt(def.minWidth));
1981
1973
 
1974
+ if (def.maxInitialWidth) {
1975
+ this.maxInitialWidth = parseInt(def.maxInitialWidth);
1976
+ }
1977
+
1982
1978
  if(def.maxWidth){
1983
1979
  this.setMaxWidth(parseInt(def.maxWidth));
1984
1980
  }
@@ -2229,6 +2225,10 @@ class Column$1 extends CoreFeature{
2229
2225
  return this.field;
2230
2226
  }
2231
2227
 
2228
+ getTitleDownload() {
2229
+ return this.titleDownload;
2230
+ }
2231
+
2232
2232
  //return the first column in a group
2233
2233
  getFirstColumn(){
2234
2234
  if(!this.isGroup){
@@ -2481,7 +2481,7 @@ class Column$1 extends CoreFeature{
2481
2481
  }
2482
2482
 
2483
2483
  getHeight(){
2484
- return this.element.offsetHeight;
2484
+ return Math.ceil(this.element.getBoundingClientRect().height);
2485
2485
  }
2486
2486
 
2487
2487
  setMinWidth(minWidth){
@@ -2585,18 +2585,19 @@ class Column$1 extends CoreFeature{
2585
2585
 
2586
2586
  //set width if present
2587
2587
  if(typeof this.definition.width !== "undefined" && !force){
2588
+ // maxInitialWidth ignored here as width specified
2588
2589
  this.setWidth(this.definition.width);
2589
2590
  }
2590
2591
 
2591
2592
  this.dispatch("column-width-fit-before", this);
2592
2593
 
2593
- this.fitToData();
2594
+ this.fitToData(force);
2594
2595
 
2595
2596
  this.dispatch("column-width-fit-after", this);
2596
2597
  }
2597
2598
 
2598
2599
  //set column width to maximum cell width for non group columns
2599
- fitToData(){
2600
+ fitToData(force){
2600
2601
  if(this.isGroup){
2601
2602
  return;
2602
2603
  }
@@ -2621,7 +2622,11 @@ class Column$1 extends CoreFeature{
2621
2622
  });
2622
2623
 
2623
2624
  if(maxWidth){
2624
- 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);
2625
2630
  }
2626
2631
  }
2627
2632
  }
@@ -2850,12 +2855,12 @@ class Row extends CoreFeature{
2850
2855
 
2851
2856
  this.dispatch("row-layout", this);
2852
2857
 
2858
+ this.initialized = true;
2859
+
2853
2860
  if(this.table.options.rowFormatter){
2854
2861
  this.table.options.rowFormatter(this.getComponent());
2855
2862
  }
2856
2863
 
2857
- this.initialized = true;
2858
-
2859
2864
  this.dispatch("row-layout-after", this);
2860
2865
  }else {
2861
2866
  this.table.columnManager.renderer.rerenderRowCells(this);
@@ -3319,7 +3324,7 @@ class ColumnCalcs extends Module{
3319
3324
  this.subscribe("row-added", this.rowsUpdated.bind(this));
3320
3325
  this.subscribe("column-moved", this.recalcActiveRows.bind(this));
3321
3326
  this.subscribe("column-add", this.recalcActiveRows.bind(this));
3322
- this.subscribe("data-refeshed", this.recalcActiveRows.bind(this));
3327
+ this.subscribe("data-refreshed", this.recalcActiveRows.bind(this));
3323
3328
  this.subscribe("table-redraw", this.tableRedraw.bind(this));
3324
3329
  this.subscribe("rows-visible", this.visibleRows.bind(this));
3325
3330
 
@@ -3812,6 +3817,7 @@ class DataTree extends Module{
3812
3817
  this.registerComponentFunction("row", "getTreeParent", this.getTreeParent.bind(this));
3813
3818
  this.registerComponentFunction("row", "getTreeChildren", this.getRowChildren.bind(this));
3814
3819
  this.registerComponentFunction("row", "addTreeChild", this.addTreeChildRow.bind(this));
3820
+ this.registerComponentFunction("row", "isTreeExpanded", this.isRowExpanded.bind(this));
3815
3821
  }
3816
3822
 
3817
3823
  initialize(){
@@ -4184,6 +4190,10 @@ class DataTree extends Module{
4184
4190
  }
4185
4191
  }
4186
4192
 
4193
+ isRowExpanded(row){
4194
+ return row.modules.dataTree.open;
4195
+ }
4196
+
4187
4197
  getTreeParent(row){
4188
4198
  return row.modules.dataTree.parent ? row.modules.dataTree.parent.getComponent() : false;
4189
4199
  }
@@ -4439,7 +4449,7 @@ function json(list, options, setFileContents){
4439
4449
  case "row":
4440
4450
  row.columns.forEach((col) => {
4441
4451
  if(col){
4442
- item[col.component.getField()] = col.value;
4452
+ item[col.component.getTitleDownload() || col.component.getField()] = col.value;
4443
4453
  }
4444
4454
  });
4445
4455
 
@@ -4670,9 +4680,43 @@ function html(list, options, setFileContents){
4670
4680
  }
4671
4681
  }
4672
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
+
4673
4716
  var defaultDownloaders = {
4674
4717
  csv:csv,
4675
4718
  json:json,
4719
+ jsonLines:jsonLines,
4676
4720
  pdf:pdf,
4677
4721
  xlsx:xlsx,
4678
4722
  html:html,
@@ -6715,12 +6759,12 @@ class Edit extends Module{
6715
6759
  this.subscribe("row-deleting", this.rowDeleteCheck.bind(this));
6716
6760
  this.subscribe("data-refeshing", this.cancelEdit.bind(this));
6717
6761
 
6718
- this.subscribe("keybinding-nav-prev", this.navigatePrev.bind(this));
6762
+ this.subscribe("keybinding-nav-prev", this.navigatePrev.bind(this, undefined));
6719
6763
  this.subscribe("keybinding-nav-next", this.keybindingNavigateNext.bind(this));
6720
- this.subscribe("keybinding-nav-left", this.navigateLeft.bind(this));
6721
- this.subscribe("keybinding-nav-right", this.navigateRight.bind(this));
6722
- this.subscribe("keybinding-nav-up", this.navigateUp.bind(this));
6723
- 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));
6724
6768
  }
6725
6769
 
6726
6770
 
@@ -6733,9 +6777,9 @@ class Edit extends Module{
6733
6777
  newRow = this.options("tabEndNewRow");
6734
6778
 
6735
6779
  if(cell){
6736
- if(!this.navigateNext(e)){
6780
+ if(!this.navigateNext(cell, e)){
6737
6781
  if(newRow){
6738
- cell.getElement().firstChild.blur();
6782
+ // cell.getElement().firstChild.blur();
6739
6783
 
6740
6784
  if(newRow === true){
6741
6785
  newRow = this.table.addRow({});
@@ -6749,7 +6793,7 @@ class Edit extends Module{
6749
6793
 
6750
6794
  newRow.then(() => {
6751
6795
  setTimeout(() => {
6752
- nav.next();
6796
+ cell.getComponent().navigateNext();
6753
6797
  });
6754
6798
  });
6755
6799
  }
@@ -6779,7 +6823,7 @@ class Edit extends Module{
6779
6823
  ///////////////////////////////////
6780
6824
  clearCellEdited(cells){
6781
6825
  if(!cells){
6782
- cells = this.modules.edit.getEditedCells();
6826
+ cells = this.table.modules.edit.getEditedCells();
6783
6827
  }
6784
6828
 
6785
6829
  if(!Array.isArray(cells)){
@@ -6787,13 +6831,12 @@ class Edit extends Module{
6787
6831
  }
6788
6832
 
6789
6833
  cells.forEach((cell) => {
6790
- this.modules.edit.clearEdited(cell._getSelf());
6834
+ this.table.modules.edit.clearEdited(cell._getSelf());
6791
6835
  });
6792
6836
  }
6793
6837
 
6794
- navigatePrev(e){
6795
- var cell = this.currentCell,
6796
- nextCell, prevRow;
6838
+ navigatePrev(cell = this.currentCell, e){
6839
+ var nextCell, prevRow;
6797
6840
 
6798
6841
  if(cell){
6799
6842
 
@@ -6822,9 +6865,8 @@ class Edit extends Module{
6822
6865
  return false;
6823
6866
  }
6824
6867
 
6825
- navigateNext(e){
6826
- var cell = this.currentCell,
6827
- nextCell, nextRow;
6868
+ navigateNext(cell = this.currentCell, e){
6869
+ var nextCell, nextRow;
6828
6870
 
6829
6871
  if(cell){
6830
6872
 
@@ -6853,9 +6895,8 @@ class Edit extends Module{
6853
6895
  return false;
6854
6896
  }
6855
6897
 
6856
- navigateLeft(e){
6857
- var cell = this.currentCell,
6858
- index, nextCell;
6898
+ navigateLeft(cell = this.currentCell, e){
6899
+ var index, nextCell;
6859
6900
 
6860
6901
  if(cell){
6861
6902
 
@@ -6875,9 +6916,8 @@ class Edit extends Module{
6875
6916
  return false;
6876
6917
  }
6877
6918
 
6878
- navigateRight(e){
6879
- var cell = this.currentCell,
6880
- index, nextCell;
6919
+ navigateRight(cell = this.currentCell, e){
6920
+ var index, nextCell;
6881
6921
 
6882
6922
  if(cell){
6883
6923
 
@@ -6897,9 +6937,8 @@ class Edit extends Module{
6897
6937
  return false;
6898
6938
  }
6899
6939
 
6900
- navigateUp(e){
6901
- var cell = this.currentCell,
6902
- index, nextRow;
6940
+ navigateUp(cell = this.currentCell, e){
6941
+ var index, nextRow;
6903
6942
 
6904
6943
  if(cell){
6905
6944
 
@@ -6919,9 +6958,8 @@ class Edit extends Module{
6919
6958
  return false;
6920
6959
  }
6921
6960
 
6922
- navigateDown(e){
6923
- var cell = this.currentCell,
6924
- index, nextRow;
6961
+ navigateDown(cell = this.currentCell, e){
6962
+ var index, nextRow;
6925
6963
 
6926
6964
  if(cell){
6927
6965
 
@@ -7065,8 +7103,6 @@ class Edit extends Module{
7065
7103
 
7066
7104
  this.invalidEdit = false;
7067
7105
 
7068
- console.log("clear", cancel, cell, cell.validate);
7069
-
7070
7106
  if(cell){
7071
7107
  this.currentCell = false;
7072
7108
 
@@ -8497,7 +8533,7 @@ class Filter extends Module{
8497
8533
 
8498
8534
  params = column.definition.headerFilterParams || {};
8499
8535
 
8500
- params = typeof params === "function" ? params.call(self.table) : params;
8536
+ params = typeof params === "function" ? params.call(self.table, cellWrapper) : params;
8501
8537
 
8502
8538
  editorElement = editor.call(this.table.modules.edit, cellWrapper, function(){}, success, cancel, params);
8503
8539
 
@@ -9186,7 +9222,7 @@ function datetime(cell, formatterParams, onRendered){
9186
9222
  var value = cell.getValue();
9187
9223
 
9188
9224
  if(typeof DT != "undefined"){
9189
- var newDatetime = DT.fromFormat(String(value), inputFormat);
9225
+ var newDatetime = inputFormat === "iso" ? DT.fromISO(String(value)) : DT.fromFormat(String(value), inputFormat);
9190
9226
 
9191
9227
  if(newDatetime.isValid){
9192
9228
 
@@ -9221,7 +9257,8 @@ function datetimediff (cell, formatterParams, onRendered) {
9221
9257
  var value = cell.getValue();
9222
9258
 
9223
9259
  if(typeof DT != "undefined"){
9224
- var newDatetime = DT.fromFormat(String(value), inputFormat);
9260
+
9261
+ var newDatetime = inputFormat === "iso" ? DT.fromISO(String(value)) : DT.fromFormat(String(value), inputFormat);
9225
9262
 
9226
9263
  if (newDatetime.isValid){
9227
9264
  if(humanize);else {
@@ -10118,6 +10155,7 @@ class FrozenRows extends Module{
10118
10155
  this.table.columnManager.getElement().insertBefore(this.topElement, this.table.columnManager.headersElement.nextSibling);
10119
10156
 
10120
10157
  this.subscribe("row-deleting", this.detachRow.bind(this));
10158
+ this.subscribe("rows-visible", this.visibleRows.bind(this));
10121
10159
 
10122
10160
  this.registerDisplayHandler(this.getRows.bind(this), 10);
10123
10161
  }
@@ -10131,6 +10169,14 @@ class FrozenRows extends Module{
10131
10169
  return !!this.rows.length;
10132
10170
  }
10133
10171
 
10172
+ visibleRows(viewable, rows){
10173
+ this.rows.forEach((row) => {
10174
+ rows.push(row);
10175
+ });
10176
+
10177
+ return rows;
10178
+ }
10179
+
10134
10180
  //filter frozen rows out of display data
10135
10181
  getRows(rows){
10136
10182
  var output = rows.slice(0);
@@ -10293,6 +10339,7 @@ class Group{
10293
10339
  this.groups = [];
10294
10340
  this.groupList = [];
10295
10341
  this.generator = generator;
10342
+ this.element = false;
10296
10343
  this.elementContents = false;
10297
10344
  this.height = 0;
10298
10345
  this.outerHeight = 0;
@@ -10360,67 +10407,7 @@ class Group{
10360
10407
  }
10361
10408
 
10362
10409
  addBindings(){
10363
- var dblTap, tapHold, tap, toggleElement;
10364
-
10365
- if ((this.groupManager.table.options.groupContextMenu || this.groupManager.table.options.groupClickMenu) && this.groupManager.table.modExists("menu")){
10366
- this.groupManager.table.modules.menu.initializeGroup.call(this.groupManager.table.modules.menu, this);
10367
- }
10368
-
10369
- if (this.groupManager.table.options.groupTap){
10370
- tap = false;
10371
-
10372
- this.element.addEventListener("touchstart", (e) => {
10373
- tap = true;
10374
- }, {passive: true});
10375
-
10376
- this.element.addEventListener("touchend", (e) => {
10377
- if(tap){
10378
- this.groupManager.table.options.groupTap(e, this.getComponent());
10379
- }
10380
-
10381
- tap = false;
10382
- });
10383
- }
10384
-
10385
- if (this.groupManager.table.options.groupDblTap){
10386
- dblTap = null;
10387
-
10388
- this.element.addEventListener("touchend", (e) => {
10389
- if(dblTap){
10390
- clearTimeout(dblTap);
10391
- dblTap = null;
10392
-
10393
- this.groupManager.table.options.groupDblTap(e, this.getComponent());
10394
- }else {
10395
-
10396
- dblTap = setTimeout(() => {
10397
- clearTimeout(dblTap);
10398
- dblTap = null;
10399
- }, 300);
10400
- }
10401
- });
10402
- }
10403
-
10404
- if (this.groupManager.table.options.groupTapHold){
10405
- tapHold = null;
10406
-
10407
- this.element.addEventListener("touchstart", (e) => {
10408
- clearTimeout(tapHold);
10409
-
10410
- tapHold = setTimeout(() => {
10411
- clearTimeout(tapHold);
10412
- tapHold = null;
10413
- tap = false;
10414
- this.groupManager.table.options.groupTapHold(e, this.getComponent());
10415
- }, 1000);
10416
-
10417
- }, {passive: true});
10418
-
10419
- this.element.addEventListener("touchend", (e) => {
10420
- clearTimeout(tapHold);
10421
- tapHold = null;
10422
- });
10423
- }
10410
+ var toggleElement;
10424
10411
 
10425
10412
  if(this.groupManager.table.options.groupToggleElement){
10426
10413
  toggleElement = this.groupManager.table.options.groupToggleElement == "arrow" ? this.arrowElement : this.element;
@@ -10979,13 +10966,13 @@ class GroupRows extends Module{
10979
10966
  initialize(){
10980
10967
  if(this.table.options.groupBy){
10981
10968
 
10982
- this.configureGroupSetup();
10983
-
10984
10969
  if(this.table.options.groupUpdateOnCellEdit){
10985
10970
  this.subscribe("cell-value-updated", this.cellUpdated.bind(this));
10986
10971
  this.subscribe("row-data-changed", this.reassignRowToGroup.bind(this), 0);
10987
10972
  }
10988
10973
 
10974
+ this.subscribe("table-built", this.configureGroupSetup.bind(this));
10975
+
10989
10976
  this.subscribe("row-deleting", this.rowDeleting.bind(this));
10990
10977
  this.subscribe("row-deleted", this.rowsUpdated.bind(this));
10991
10978
  this.subscribe("scroll-horizontal", this.scrollHeaders.bind(this));
@@ -11904,60 +11891,327 @@ class HtmlTableImport extends Module{
11904
11891
 
11905
11892
  HtmlTableImport.moduleName = "htmlTableImport";
11906
11893
 
11907
- 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
+ }
11908
11909
 
11909
- constructor(table){
11910
- 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
+ }
11911
11948
 
11912
- this.eventMap = {
11913
- //row events
11914
- rowClick:"row-click",
11915
- rowDblClick:"row-dblclick",
11916
- rowContext:"row-contextmenu",
11917
- rowMouseEnter:"row-mouseenter",
11918
- rowMouseLeave:"row-mouseleave",
11919
- rowMouseOver:"row-mouseover",
11920
- rowMouseOut:"row-mouseout",
11921
- rowMouseMove:"row-mousemove",
11922
- rowTap:"row",
11923
- rowDblTap:"row",
11924
- rowTapHold:"row",
11949
+ //Normal Character, append to column
11950
+ data[row][col] += char;
11951
+ }
11925
11952
 
11926
- //cell events
11927
- cellClick:"cell-click",
11928
- cellDblClick:"cell-dblclick",
11929
- cellContext:"cell-contextmenu",
11930
- cellMouseEnter:"cell-mouseenter",
11931
- cellMouseLeave:"cell-mouseleave",
11932
- cellMouseOver:"cell-mouseover",
11933
- cellMouseOut:"cell-mouseout",
11934
- cellMouseMove:"cell-mousemove",
11935
- cellTap:"cell",
11936
- cellDblTap:"cell",
11937
- 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));
11938
11981
 
11939
- //column header events
11940
- headerClick:"column-click",
11941
- headerDblClick:"column-dblclick",
11942
- headerContext:"column-contextmenu",
11943
- headerMouseEnter:"column-mouseenter",
11944
- headerMouseLeave:"column-mouseleave",
11945
- headerMouseOver:"column-mouseover",
11946
- headerMouseOut:"column-mouseout",
11947
- headerMouseMove:"column-mousemove",
11948
- headerTap:"column",
11949
- headerDblTap:"column",
11950
- headerTapHold:"column",
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
+ }
11951
11987
 
11952
- //group header
11953
- groupClick:"group-click",
11954
- groupDblClick:"group-dblclick",
11955
- groupContext:"group-contextmenu",
11956
- groupMouseEnter:"group-mouseenter",
11957
- groupMouseLeave:"group-mouseleave",
11958
- groupMouseOver:"group-mouseover",
11959
- groupMouseOut:"group-mouseout",
11960
- groupMouseMove:"group-mousemove",
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",
12195
+ headerDblClick:"column-dblclick",
12196
+ headerContext:"column-contextmenu",
12197
+ headerMouseEnter:"column-mouseenter",
12198
+ headerMouseLeave:"column-mouseleave",
12199
+ headerMouseOver:"column-mouseover",
12200
+ headerMouseOut:"column-mouseout",
12201
+ headerMouseMove:"column-mousemove",
12202
+ headerTap:"column",
12203
+ headerDblTap:"column",
12204
+ headerTapHold:"column",
12205
+
12206
+ //group header
12207
+ groupClick:"group-click",
12208
+ groupDblClick:"group-dblclick",
12209
+ groupContext:"group-contextmenu",
12210
+ groupMouseEnter:"group-mouseenter",
12211
+ groupMouseLeave:"group-mouseleave",
12212
+ groupMouseOver:"group-mouseover",
12213
+ groupMouseOut:"group-mouseout",
12214
+ groupMouseMove:"group-mousemove",
11961
12215
  groupTap:"group",
11962
12216
  groupDblTap:"group",
11963
12217
  groupTapHold:"group",
@@ -11984,6 +12238,11 @@ class Interaction extends Module{
11984
12238
  tap:null,
11985
12239
  tapDbl:null,
11986
12240
  tapHold:null,
12241
+ },
12242
+ group:{
12243
+ tap:null,
12244
+ tapDbl:null,
12245
+ tapHold:null,
11987
12246
  }
11988
12247
  };
11989
12248
 
@@ -12214,9 +12473,9 @@ var defaultBindings = {
12214
12473
  scrollPageDown:34,
12215
12474
  scrollToStart:36,
12216
12475
  scrollToEnd:35,
12217
- undo:"ctrl + 90",
12218
- redo:"ctrl + 89",
12219
- copyToClipboard:"ctrl + 67",
12476
+ undo:["ctrl + 90", "meta + 90"],
12477
+ redo:["ctrl + 89", "meta + 89"],
12478
+ copyToClipboard:["ctrl + 67", "meta + 89"],
12220
12479
  };
12221
12480
 
12222
12481
  var defaultActions = {
@@ -12350,7 +12609,7 @@ class Keybindings extends Module{
12350
12609
  this.keyupBinding = false;
12351
12610
  this.keydownBinding = false;
12352
12611
 
12353
- this.registerTableOption("keybindings", []); //array for keybindings
12612
+ this.registerTableOption("keybindings", {}); //array for keybindings
12354
12613
  this.registerTableOption("tabEndNewRow", false); //create new row when tab to end of table
12355
12614
  }
12356
12615
 
@@ -12362,17 +12621,8 @@ class Keybindings extends Module{
12362
12621
  this.pressedKeys = [];
12363
12622
 
12364
12623
  if(bindings !== false){
12365
-
12366
- for(let key in Keybindings.bindings){
12367
- mergedBindings[key] = Keybindings.bindings[key];
12368
- }
12369
-
12370
- if(Object.keys(bindings).length){
12371
-
12372
- for(let key in bindings){
12373
- mergedBindings[key] = bindings[key];
12374
- }
12375
- }
12624
+ Object.assign(mergedBindings, Keybindings.bindings);
12625
+ Object.assign(mergedBindings, bindings);
12376
12626
 
12377
12627
  this.mapBindings(mergedBindings);
12378
12628
  this.bindEvents();
@@ -12390,7 +12640,11 @@ class Keybindings extends Module{
12390
12640
  }
12391
12641
 
12392
12642
  bindings[key].forEach((binding) => {
12393
- this.mapBinding(key, binding);
12643
+ var bindingList = Array.isArray(binding) ? binding : [binding];
12644
+
12645
+ bindingList.forEach((item) => {
12646
+ this.mapBinding(key, item);
12647
+ });
12394
12648
  });
12395
12649
  }
12396
12650
  }else {
@@ -12425,7 +12679,7 @@ class Keybindings extends Module{
12425
12679
  break;
12426
12680
 
12427
12681
  default:
12428
- symbol = parseInt(symbol);
12682
+ symbol = isNaN(symbol) ? symbol.toUpperCase().charCodeAt(0) : parseInt(symbol);
12429
12683
  binding.keys.push(symbol);
12430
12684
 
12431
12685
  if(!this.watchKeys[symbol]){
@@ -12513,164 +12767,193 @@ Keybindings.bindings = defaultBindings;
12513
12767
  Keybindings.actions = defaultActions;
12514
12768
 
12515
12769
  class Menu extends Module{
12516
-
12770
+
12517
12771
  constructor(table){
12518
12772
  super(table);
12519
-
12773
+
12774
+ this.menuContainer = null;
12520
12775
  this.menuElements = [];
12521
12776
  this.blurEvent = this.hideMenu.bind(this);
12522
12777
  this.escEvent = this.escMenu.bind(this);
12523
12778
  this.nestedMenuBlock = false;
12524
12779
  this.positionReversedX = false;
12525
-
12780
+
12781
+ this.currentComponent = null;
12782
+
12783
+ this.columnSubscribers = {};
12784
+
12526
12785
  this.registerTableOption("rowContextMenu", false);
12527
12786
  this.registerTableOption("rowClickMenu", false);
12528
12787
  this.registerTableOption("groupContextMenu", false);
12529
12788
  this.registerTableOption("groupClickMenu", false);
12530
-
12789
+ this.registerTableOption("menuContainer", false);
12790
+
12531
12791
  this.registerColumnOption("headerContextMenu");
12792
+ this.registerColumnOption("headerClickMenu");
12532
12793
  this.registerColumnOption("headerMenu");
12533
12794
  this.registerColumnOption("contextMenu");
12534
12795
  this.registerColumnOption("clickMenu");
12535
12796
  }
12536
-
12797
+
12537
12798
  initialize(){
12538
- this.subscribe("cell-layout", this.layoutCell.bind(this));
12799
+ this.lookupMenuContainer();
12800
+
12801
+ this.initializeRowWatchers();
12802
+ this.initializeGroupWatchers();
12803
+
12539
12804
  this.subscribe("column-init", this.initializeColumn.bind(this));
12540
- this.subscribe("row-init", this.initializeRow.bind(this));
12541
12805
  }
12542
-
12543
- layoutCell(cell){
12544
- if(cell.column.definition.contextMenu || cell.column.definition.clickMenu){
12545
- 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;
12546
12828
  }
12547
12829
  }
12548
-
12549
- initializeColumn(column){
12550
- var def = column.definition;
12551
-
12552
- if(def.headerContextMenu || def.headerClickMenu || def.headerMenu){
12553
- this.initializeColumnHeader(column);
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;
12554
12836
  }
12555
12837
  }
12556
-
12557
- initializeColumnHeader(column){
12558
- var headerMenuEl;
12559
-
12560
- if(column.definition.headerContextMenu){
12561
- column.getElement().addEventListener("contextmenu", this.LoadMenuEvent.bind(this, column, column.definition.headerContextMenu));
12562
- this.tapHold(column, column.definition.headerContextMenu);
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));
12563
12843
  }
12564
-
12565
- // if(column.definition.headerClickMenu){
12566
- // column.getElement().addEventListener("click", this.LoadMenuEvent.bind(this, column, column.definition.headerClickMenu));
12567
- // }
12568
-
12569
- if(column.definition.headerMenu){
12570
-
12571
- headerMenuEl = document.createElement("span");
12572
- headerMenuEl.classList.add("tabulator-header-menu-button");
12573
- headerMenuEl.innerHTML = "&vellip;";
12574
-
12575
- headerMenuEl.addEventListener("click", (e) => {
12576
- e.stopPropagation();
12577
- e.preventDefault();
12578
-
12579
- this.LoadMenuEvent(column, column.definition.headerMenu, e);
12580
- });
12581
-
12582
- column.titleElement.insertBefore(headerMenuEl, column.titleElement.firstChild);
12844
+
12845
+ if(this.table.options.rowClickMenu){
12846
+ this.subscribe("row-click", this.loadMenuEvent.bind(this, this.table.options.rowClickMenu));
12583
12847
  }
12584
12848
  }
12585
-
12586
- LoadMenuEvent(component, menu, e){
12587
- menu = typeof menu == "function" ? menu.call(this.table, component.getComponent(), e) : menu;
12588
-
12589
- // if(component instanceof Cell){
12590
- // e.stopImmediatePropagation();
12591
- // }
12592
-
12593
- this.loadMenu(e, component, menu);
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));
12854
+ }
12855
+
12856
+ if(this.table.options.groupClickMenu){
12857
+ this.subscribe("group-click", this.loadMenuEvent.bind(this, this.table.options.groupClickMenu));
12858
+ }
12594
12859
  }
12595
-
12596
- tapHold(component, menu){
12597
- var element = component.getElement(),
12598
- tapHold = null,
12599
- loaded = false;
12600
-
12601
- element.addEventListener("touchstart", (e) => {
12602
- clearTimeout(tapHold);
12603
- loaded = false;
12604
-
12605
- tapHold = setTimeout(() => {
12606
- clearTimeout(tapHold);
12607
- tapHold = null;
12608
- loaded = true;
12609
-
12610
- this.LoadMenuEvent(component, menu, e);
12611
- }, 1000);
12612
-
12613
- }, {passive: true});
12614
-
12615
- element.addEventListener("touchend", (e) => {
12616
- clearTimeout(tapHold);
12617
- tapHold = null;
12618
-
12619
- if(loaded){
12620
- e.preventDefault();
12621
- }
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);
12622
12905
  });
12906
+
12907
+ column.titleElement.insertBefore(headerMenuEl, column.titleElement.firstChild);
12623
12908
  }
12624
-
12625
- initializeCell(cell){
12626
- if(cell.column.definition.contextMenu){
12627
- cell.getElement(true).addEventListener("contextmenu", this.LoadMenuEvent.bind(this, cell, cell.column.definition.contextMenu));
12628
- this.tapHold(cell, cell.column.definition.contextMenu);
12909
+
12910
+ loadMenuTableCellEvent(option, e, cell){
12911
+ if(cell._cell){
12912
+ cell = cell._cell;
12629
12913
  }
12630
-
12631
- if(cell.column.definition.clickMenu){
12632
- 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);
12633
12917
  }
12634
12918
  }
12635
-
12636
- initializeRow(row){
12637
- if(this.table.options.rowContextMenu){
12638
- row.getElement().addEventListener("contextmenu", this.LoadMenuEvent.bind(this, row, this.table.options.rowContextMenu));
12639
- this.tapHold(row, this.table.options.rowContextMenu);
12919
+
12920
+ loadMenuTableColumnEvent(option, e, column){
12921
+ if(column._column){
12922
+ column = column._column;
12640
12923
  }
12641
-
12642
- if(this.table.options.rowClickMenu){
12643
- 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);
12644
12927
  }
12645
12928
  }
12646
-
12647
- initializeGroup (group){
12648
- if(this.table.options.groupContextMenu){
12649
- group.getElement().addEventListener("contextmenu", this.LoadMenuEvent.bind(this, group, this.table.options.groupContextMenu));
12650
- this.tapHold(group, this.table.options.groupContextMenu);
12651
- }
12652
-
12653
- if(this.table.options.groupClickMenu){
12654
- 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;
12655
12935
  }
12936
+
12937
+ menu = typeof menu == "function" ? menu.call(this.table, component.getComponent(), e) : menu;
12938
+
12939
+ this.loadMenu(e, component, menu);
12656
12940
  }
12657
-
12941
+
12658
12942
  loadMenu(e, component, menu, parentEl){
12659
-
12660
12943
  var touch = !(e instanceof MouseEvent);
12661
-
12944
+
12662
12945
  var menuEl = document.createElement("div");
12663
12946
  menuEl.classList.add("tabulator-menu");
12664
-
12947
+
12665
12948
  if(!touch){
12666
12949
  e.preventDefault();
12667
12950
  }
12668
-
12951
+
12669
12952
  //abort if no menu set
12670
12953
  if(!menu || !menu.length){
12671
12954
  return;
12672
12955
  }
12673
-
12956
+
12674
12957
  if(!parentEl){
12675
12958
  if(this.nestedMenuBlock){
12676
12959
  //abort if child menu already open
@@ -12682,35 +12965,35 @@ class Menu extends Module{
12682
12965
  this.nestedMenuBlock = false;
12683
12966
  }, 100);
12684
12967
  }
12685
-
12968
+
12686
12969
  this.hideMenu();
12687
12970
  this.menuElements = [];
12688
12971
  }
12689
-
12972
+
12690
12973
  menu.forEach((item) => {
12691
12974
  var itemEl = document.createElement("div"),
12692
12975
  label = item.label,
12693
12976
  disabled = item.disabled;
12694
-
12977
+
12695
12978
  if(item.separator){
12696
12979
  itemEl.classList.add("tabulator-menu-separator");
12697
12980
  }else {
12698
12981
  itemEl.classList.add("tabulator-menu-item");
12699
-
12982
+
12700
12983
  if(typeof label == "function"){
12701
12984
  label = label.call(this.table, component.getComponent());
12702
12985
  }
12703
-
12986
+
12704
12987
  if(label instanceof Node){
12705
12988
  itemEl.appendChild(label);
12706
12989
  }else {
12707
12990
  itemEl.innerHTML = label;
12708
12991
  }
12709
-
12992
+
12710
12993
  if(typeof disabled == "function"){
12711
12994
  disabled = disabled.call(this.table, component.getComponent());
12712
12995
  }
12713
-
12996
+
12714
12997
  if(disabled){
12715
12998
  itemEl.classList.add("tabulator-menu-item-disabled");
12716
12999
  itemEl.addEventListener("click", (e) => {
@@ -12731,57 +13014,67 @@ class Menu extends Module{
12731
13014
  }
12732
13015
  }
12733
13016
  }
12734
-
13017
+
12735
13018
  if(item.menu && item.menu.length){
12736
13019
  itemEl.classList.add("tabulator-menu-item-submenu");
12737
13020
  }
12738
13021
  }
12739
-
13022
+
12740
13023
  menuEl.appendChild(itemEl);
12741
13024
  });
12742
-
13025
+
12743
13026
  menuEl.addEventListener("click", (e) => {
12744
13027
  this.hideMenu();
12745
13028
  });
12746
-
13029
+
12747
13030
  this.menuElements.push(menuEl);
12748
13031
  this.positionMenu(menuEl, parentEl, touch, e);
13032
+
13033
+ this.currentComponent = component;
13034
+
13035
+ this.dispatchExternal("menuOpened", component.getComponent());
12749
13036
  }
12750
-
13037
+
12751
13038
  hideOldSubMenus(menuEl){
12752
13039
  var index = this.menuElements.indexOf(menuEl);
12753
-
13040
+
12754
13041
  if(index > -1){
12755
13042
  for(let i = this.menuElements.length - 1; i > index; i--){
12756
13043
  var el = this.menuElements[i];
12757
-
13044
+
12758
13045
  if(el.parentNode){
12759
13046
  el.parentNode.removeChild(el);
12760
13047
  }
12761
-
13048
+
12762
13049
  this.menuElements.pop();
12763
13050
  }
12764
13051
  }
12765
13052
  }
12766
-
13053
+
12767
13054
  positionMenu(element, parentEl, touch, e){
12768
- var docHeight = Math.max(document.body.offsetHeight, window.innerHeight),
12769
- x, y, parentOffset;
12770
-
13055
+ var x, y, parentOffset;
13056
+
12771
13057
  if(!parentEl){
12772
13058
  x = touch ? e.touches[0].pageX : e.pageX;
12773
13059
  y = touch ? e.touches[0].pageY : e.pageY;
12774
-
13060
+
13061
+ if(this.menuContainer !== document.body){
13062
+ parentOffset = Helpers.elOffset(this.menuContainer);
13063
+
13064
+ x -= parentOffset.left;
13065
+ y -= parentOffset.top;
13066
+ }
13067
+
12775
13068
  this.positionReversedX = false;
12776
13069
  }else {
12777
13070
  parentOffset = Helpers.elOffset(parentEl);
12778
13071
  x = parentOffset.left + parentEl.offsetWidth;
12779
13072
  y = parentOffset.top - 1;
12780
13073
  }
12781
-
13074
+
12782
13075
  element.style.top = y + "px";
12783
13076
  element.style.left = x + "px";
12784
-
13077
+
12785
13078
  setTimeout(() => {
12786
13079
  this.table.rowManager.element.addEventListener("scroll", this.blurEvent);
12787
13080
  document.body.addEventListener("click", this.blurEvent);
@@ -12789,56 +13082,61 @@ class Menu extends Module{
12789
13082
  window.addEventListener("resize", this.blurEvent);
12790
13083
  document.body.addEventListener("keydown", this.escEvent);
12791
13084
  }, 100);
12792
-
12793
- document.body.appendChild(element);
12794
-
12795
- //move menu to start on bottom edge if it is too close to the edge of the screen
12796
- if((y + element.offsetHeight) >= docHeight){
12797
- element.style.top = "";
12798
-
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
+
12799
13092
  if(parentEl){
12800
- element.style.bottom = (docHeight - parentOffset.top - parentEl.offsetHeight - 1) + "px";
13093
+ element.style.right = (this.menuContainer.offsetWidth - parentOffset.left) + "px";
12801
13094
  }else {
12802
- element.style.bottom = (docHeight - y) + "px";
13095
+ element.style.right = (this.menuContainer.offsetWidth - x) + "px";
12803
13096
  }
13097
+
13098
+ this.positionReversedX = true;
12804
13099
  }
12805
-
12806
- //move menu to start on right edge if it is too close to the edge of the screen
12807
- if((x + element.offsetWidth) >= document.body.offsetWidth || this.positionReversedX){
12808
- element.style.left = "";
12809
-
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
+
12810
13105
  if(parentEl){
12811
- element.style.right = (document.documentElement.offsetWidth - parentOffset.left) + "px";
13106
+ element.style.bottom = (this.menuContainer.offsetHeight - parentOffset.top - parentEl.offsetHeight - 1) + "px";
12812
13107
  }else {
12813
- element.style.right = (document.documentElement.offsetWidth - x) + "px";
13108
+ element.style.bottom = (this.menuContainer.offsetHeight - y) + "px";
12814
13109
  }
12815
-
12816
- this.positionReversedX = true;
12817
13110
  }
12818
13111
  }
12819
-
13112
+
12820
13113
  isOpen(){
12821
13114
  return !!this.menuElements.length;
12822
13115
  }
12823
-
13116
+
12824
13117
  escMenu(e){
12825
13118
  if(e.keyCode == 27){
12826
13119
  this.hideMenu();
12827
13120
  }
12828
13121
  }
12829
-
12830
- hideMenu(){
13122
+
13123
+ hideMenu(){
12831
13124
  this.menuElements.forEach((menuEl) => {
12832
13125
  if(menuEl.parentNode){
12833
13126
  menuEl.parentNode.removeChild(menuEl);
12834
13127
  }
12835
13128
  });
12836
-
13129
+
12837
13130
  document.body.removeEventListener("keydown", this.escEvent);
12838
13131
  document.body.removeEventListener("click", this.blurEvent);
12839
13132
  document.body.removeEventListener("contextmenu", this.blurEvent);
12840
13133
  window.removeEventListener("resize", this.blurEvent);
12841
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
+ }
12842
13140
  }
12843
13141
  }
12844
13142
 
@@ -13456,6 +13754,8 @@ class MoveRows extends Module{
13456
13754
  document.body.addEventListener("mousemove", this.moveHover);
13457
13755
  document.body.addEventListener("mouseup", this.endMove);
13458
13756
 
13757
+ this.dispatchExternal("rowMoving", row.getComponent());
13758
+
13459
13759
  this.moveHover(e);
13460
13760
  }
13461
13761
 
@@ -13490,6 +13790,8 @@ class MoveRows extends Module{
13490
13790
 
13491
13791
  if(this.toRow){
13492
13792
  this.table.rowManager.moveRow(this.moving, this.toRow, this.toRowAfter);
13793
+ }else {
13794
+ this.dispatchExternal("rowMoveCancelled", this.moving.getComponent());
13493
13795
  }
13494
13796
 
13495
13797
  this.moving = false;
@@ -13904,41 +14206,121 @@ Mutator.moduleName = "mutator";
13904
14206
  //load defaults
13905
14207
  Mutator.mutators = defaultMutators;
13906
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
+
13907
14281
  class Page extends Module{
13908
-
14282
+
13909
14283
  constructor(table){
13910
14284
  super(table);
13911
-
14285
+
13912
14286
  this.mode = "local";
13913
14287
  this.progressiveLoad = false;
13914
-
14288
+
14289
+ this.element = null;
14290
+ this.pageCounterElement = null;
14291
+ this.pageCounter = null;
14292
+
13915
14293
  this.size = 0;
13916
14294
  this.page = 1;
13917
14295
  this.count = 5;
13918
14296
  this.max = 1;
13919
14297
 
14298
+ this.remoteRowCountEstimate = null;
14299
+
13920
14300
  this.displayIndex = 0; //index in display pipeline
13921
-
14301
+
13922
14302
  this.initialLoad = true;
13923
14303
  this.dataChanging = false; //flag to check if data is being changed by this module
13924
-
14304
+
13925
14305
  this.pageSizes = [];
13926
-
14306
+
13927
14307
  this.registerTableOption("pagination", false); //set pagination type
13928
14308
  this.registerTableOption("paginationMode", "local"); //local or remote pagination
13929
14309
  this.registerTableOption("paginationSize", false); //set number of rows to a page
13930
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
13931
14313
  this.registerTableOption("paginationButtonCount", 5); // set count of page button
13932
14314
  this.registerTableOption("paginationSizeSelector", false); //add pagination size selector element
13933
14315
  this.registerTableOption("paginationElement", false); //element to hold pagination numbers
13934
14316
  // this.registerTableOption("paginationDataSent", {}); //pagination data sent to the server
13935
14317
  // this.registerTableOption("paginationDataReceived", {}); //pagination data received from the server
13936
14318
  this.registerTableOption("paginationAddRow", "page"); //add rows on table or page
13937
-
14319
+
13938
14320
  this.registerTableOption("progressiveLoad", false); //progressive loading
13939
14321
  this.registerTableOption("progressiveLoadDelay", 0); //delay between requests
13940
14322
  this.registerTableOption("progressiveLoadScrollMargin", 0); //margin before scroll begins
13941
-
14323
+
13942
14324
  this.registerTableFunction("setMaxPage", this.setMaxPage.bind(this));
13943
14325
  this.registerTableFunction("setPage", this.setPage.bind(this));
13944
14326
  this.registerTableFunction("setPageToRow", this.userSetPageToRow.bind(this));
@@ -13948,11 +14330,11 @@ class Page extends Module{
13948
14330
  this.registerTableFunction("nextPage", this.nextPage.bind(this));
13949
14331
  this.registerTableFunction("getPage", this.getPage.bind(this));
13950
14332
  this.registerTableFunction("getPageMax", this.getPageMax.bind(this));
13951
-
14333
+
13952
14334
  //register component functions
13953
14335
  this.registerComponentFunction("row", "pageTo", this.setPageToRow.bind(this));
13954
14336
  }
13955
-
14337
+
13956
14338
  initialize(){
13957
14339
  if(this.table.options.pagination){
13958
14340
  this.subscribe("row-deleted", this.rowsUpdated.bind(this));
@@ -13960,40 +14342,41 @@ class Page extends Module{
13960
14342
  this.subscribe("row-added", this.rowsUpdated.bind(this));
13961
14343
  this.subscribe("data-processed", this.initialLoadComplete.bind(this));
13962
14344
  this.subscribe("table-built", this.calculatePageSizes.bind(this));
13963
-
14345
+
13964
14346
  if(this.table.options.paginationMode === "remote"){
13965
14347
  this.subscribe("data-params", this.remotePageParams.bind(this));
13966
14348
  this.subscribe("data-loaded", this._parseRemoteData.bind(this));
13967
14349
  }
13968
-
14350
+
13969
14351
  if(this.table.options.progressiveLoad){
13970
14352
  console.error("Progressive Load Error - Pagination and progressive load cannot be used at the same time");
13971
14353
  }
13972
-
14354
+
13973
14355
  this.registerDisplayHandler(this.restOnRenderBefore.bind(this), 40);
13974
14356
  this.registerDisplayHandler(this.getRows.bind(this), 50);
13975
-
14357
+
13976
14358
  this.createElements();
14359
+ this.initializePageCounter();
13977
14360
  this.initializePaginator();
13978
14361
  }else if(this.table.options.progressiveLoad){
13979
14362
  this.subscribe("data-params", this.remotePageParams.bind(this));
13980
14363
  this.subscribe("data-loaded", this._parseRemoteData.bind(this));
13981
14364
  this.subscribe("table-built", this.calculatePageSizes.bind(this));
13982
14365
  this.subscribe("data-processed", this.initialLoadComplete.bind(this));
13983
-
14366
+
13984
14367
  this.initializeProgressive(this.table.options.progressiveLoad);
13985
-
14368
+
13986
14369
  if(this.table.options.progressiveLoad === "scroll"){
13987
14370
  this.subscribe("scroll-vertical", this.scrollVertical.bind(this));
13988
14371
  }
13989
14372
  }
13990
14373
  }
13991
-
14374
+
13992
14375
  rowAddingPosition(row, top){
13993
14376
  var rowManager = this.table.rowManager,
13994
14377
  dispRows = rowManager.getDisplayRows(),
13995
14378
  index;
13996
-
14379
+
13997
14380
  if(top){
13998
14381
  if(dispRows.length){
13999
14382
  index = dispRows[0];
@@ -14009,74 +14392,74 @@ class Page extends Module{
14009
14392
  top = dispRows.length < this.size ? false : true;
14010
14393
  }
14011
14394
  }
14012
-
14395
+
14013
14396
  return {index, top}
14014
14397
  }
14015
-
14398
+
14016
14399
  calculatePageSizes(){
14017
14400
  var testElRow, testElCell;
14018
-
14401
+
14019
14402
  if(this.table.options.paginationSize){
14020
14403
  this.size = this.table.options.paginationSize;
14021
14404
  }else {
14022
14405
  testElRow = document.createElement("div");
14023
14406
  testElRow.classList.add("tabulator-row");
14024
14407
  testElRow.style.visibility = "hidden";
14025
-
14408
+
14026
14409
  testElCell = document.createElement("div");
14027
14410
  testElCell.classList.add("tabulator-cell");
14028
14411
  testElCell.innerHTML = "Page Row Test";
14029
-
14412
+
14030
14413
  testElRow.appendChild(testElCell);
14031
-
14414
+
14032
14415
  this.table.rowManager.getTableElement().appendChild(testElRow);
14033
-
14416
+
14034
14417
  this.size = Math.floor(this.table.rowManager.getElement().clientHeight / testElRow.offsetHeight);
14035
-
14418
+
14036
14419
  this.table.rowManager.getTableElement().removeChild(testElRow);
14037
14420
  }
14038
-
14421
+
14039
14422
  this.generatePageSizeSelectList();
14040
14423
  }
14041
-
14424
+
14042
14425
  initialLoadComplete(){
14043
14426
  this.initialLoad = false;
14044
14427
  }
14045
-
14428
+
14046
14429
  remotePageParams(data, config, silent, params){
14047
14430
  if(!this.initialLoad){
14048
14431
  if((this.progressiveLoad && !silent) || (!this.progressiveLoad && !this.dataChanging)){
14049
14432
  this.reset(true);
14050
14433
  }
14051
14434
  }
14052
-
14435
+
14053
14436
  //configure request params
14054
14437
  params.page = this.page;
14055
-
14438
+
14056
14439
  //set page size if defined
14057
14440
  if(this.size){
14058
14441
  params.size = this.size;
14059
14442
  }
14060
-
14443
+
14061
14444
  return params;
14062
14445
  }
14063
-
14446
+
14064
14447
  ///////////////////////////////////
14065
14448
  ///////// Table Functions /////////
14066
14449
  ///////////////////////////////////
14067
-
14450
+
14068
14451
  userSetPageToRow(row){
14069
14452
  if(this.table.options.pagination){
14070
14453
  row = this.rowManager.findRow(row);
14071
-
14454
+
14072
14455
  if(row){
14073
14456
  return this.setPageToRow(row)
14074
14457
  }
14075
14458
  }
14076
-
14459
+
14077
14460
  return Promise.reject();
14078
14461
  }
14079
-
14462
+
14080
14463
  userSetPageSize(size){
14081
14464
  if(this.table.options.pagination){
14082
14465
  this.setPageSize(size);
@@ -14088,102 +14471,102 @@ class Page extends Module{
14088
14471
  ///////////////////////////////////
14089
14472
  ///////// Internal Logic //////////
14090
14473
  ///////////////////////////////////
14091
-
14474
+
14092
14475
  scrollVertical(top, dir){
14093
14476
  var element, diff, margin;
14094
14477
  if(!dir && !this.table.dataLoader.loading){
14095
14478
  element = this.table.rowManager.getElement();
14096
14479
  diff = element.scrollHeight - element.clientHeight - top;
14097
14480
  margin = this.table.options.progressiveLoadScrollMargin || (element.clientHeight * 2);
14098
-
14481
+
14099
14482
  if(diff < margin){
14100
14483
  this.nextPage()
14101
14484
  .catch(() => {}); //consume the exception thrown when on the last page
14102
14485
  }
14103
14486
  }
14104
14487
  }
14105
-
14488
+
14106
14489
  restOnRenderBefore(rows, renderInPosition){
14107
14490
  if(!renderInPosition){
14108
14491
  if(this.mode === "local"){
14109
14492
  this.reset();
14110
14493
  }
14111
14494
  }
14112
-
14495
+
14113
14496
  return rows;
14114
14497
  }
14115
-
14498
+
14116
14499
  rowsUpdated(){
14117
14500
  this.refreshData(true, "all");
14118
14501
  }
14119
-
14502
+
14120
14503
  createElements(){
14121
14504
  var button;
14122
-
14505
+
14123
14506
  this.element = document.createElement("span");
14124
14507
  this.element.classList.add("tabulator-paginator");
14125
-
14508
+
14126
14509
  this.pagesElement = document.createElement("span");
14127
14510
  this.pagesElement.classList.add("tabulator-pages");
14128
-
14511
+
14129
14512
  button = document.createElement("button");
14130
14513
  button.classList.add("tabulator-page");
14131
14514
  button.setAttribute("type", "button");
14132
14515
  button.setAttribute("role", "button");
14133
14516
  button.setAttribute("aria-label", "");
14134
14517
  button.setAttribute("title", "");
14135
-
14518
+
14136
14519
  this.firstBut = button.cloneNode(true);
14137
14520
  this.firstBut.setAttribute("data-page", "first");
14138
-
14521
+
14139
14522
  this.prevBut = button.cloneNode(true);
14140
14523
  this.prevBut.setAttribute("data-page", "prev");
14141
-
14524
+
14142
14525
  this.nextBut = button.cloneNode(true);
14143
14526
  this.nextBut.setAttribute("data-page", "next");
14144
-
14527
+
14145
14528
  this.lastBut = button.cloneNode(true);
14146
14529
  this.lastBut.setAttribute("data-page", "last");
14147
-
14530
+
14148
14531
  if(this.table.options.paginationSizeSelector){
14149
14532
  this.pageSizeSelect = document.createElement("select");
14150
14533
  this.pageSizeSelect.classList.add("tabulator-page-size");
14151
14534
  }
14152
14535
  }
14153
-
14536
+
14154
14537
  generatePageSizeSelectList(){
14155
14538
  var pageSizes = [];
14156
-
14539
+
14157
14540
  if(this.pageSizeSelect){
14158
-
14541
+
14159
14542
  if(Array.isArray(this.table.options.paginationSizeSelector)){
14160
14543
  pageSizes = this.table.options.paginationSizeSelector;
14161
14544
  this.pageSizes = pageSizes;
14162
-
14545
+
14163
14546
  if(this.pageSizes.indexOf(this.size) == -1){
14164
14547
  pageSizes.unshift(this.size);
14165
14548
  }
14166
14549
  }else {
14167
-
14550
+
14168
14551
  if(this.pageSizes.indexOf(this.size) == -1){
14169
14552
  pageSizes = [];
14170
-
14553
+
14171
14554
  for (let i = 1; i < 5; i++){
14172
14555
  pageSizes.push(this.size * i);
14173
14556
  }
14174
-
14557
+
14175
14558
  this.pageSizes = pageSizes;
14176
14559
  }else {
14177
14560
  pageSizes = this.pageSizes;
14178
14561
  }
14179
14562
  }
14180
-
14563
+
14181
14564
  while(this.pageSizeSelect.firstChild) this.pageSizeSelect.removeChild(this.pageSizeSelect.firstChild);
14182
-
14565
+
14183
14566
  pageSizes.forEach((item) => {
14184
14567
  var itemEl = document.createElement("option");
14185
14568
  itemEl.value = item;
14186
-
14569
+
14187
14570
  if(item === true){
14188
14571
  this.langBind("pagination|all", function(value){
14189
14572
  itemEl.innerHTML = value;
@@ -14191,136 +14574,178 @@ class Page extends Module{
14191
14574
  }else {
14192
14575
  itemEl.innerHTML = item;
14193
14576
  }
14194
-
14195
-
14196
-
14577
+
14578
+
14579
+
14197
14580
  this.pageSizeSelect.appendChild(itemEl);
14198
14581
  });
14199
-
14582
+
14200
14583
  this.pageSizeSelect.value = this.size;
14201
14584
  }
14202
14585
  }
14203
-
14204
- //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
14205
14610
  initializePaginator(hidden){
14206
- var pageSelectLabel;
14207
-
14611
+ var pageSelectLabel, paginationCounterHolder;
14612
+
14208
14613
  if(!hidden){
14209
14614
  //build pagination element
14210
-
14615
+
14211
14616
  //bind localizations
14212
14617
  this.langBind("pagination|first", (value) => {
14213
14618
  this.firstBut.innerHTML = value;
14214
14619
  });
14215
-
14620
+
14216
14621
  this.langBind("pagination|first_title", (value) => {
14217
14622
  this.firstBut.setAttribute("aria-label", value);
14218
14623
  this.firstBut.setAttribute("title", value);
14219
14624
  });
14220
-
14625
+
14221
14626
  this.langBind("pagination|prev", (value) => {
14222
14627
  this.prevBut.innerHTML = value;
14223
14628
  });
14224
-
14629
+
14225
14630
  this.langBind("pagination|prev_title", (value) => {
14226
14631
  this.prevBut.setAttribute("aria-label", value);
14227
14632
  this.prevBut.setAttribute("title", value);
14228
14633
  });
14229
-
14634
+
14230
14635
  this.langBind("pagination|next", (value) => {
14231
14636
  this.nextBut.innerHTML = value;
14232
14637
  });
14233
-
14638
+
14234
14639
  this.langBind("pagination|next_title", (value) => {
14235
14640
  this.nextBut.setAttribute("aria-label", value);
14236
14641
  this.nextBut.setAttribute("title", value);
14237
14642
  });
14238
-
14643
+
14239
14644
  this.langBind("pagination|last", (value) => {
14240
14645
  this.lastBut.innerHTML = value;
14241
14646
  });
14242
-
14647
+
14243
14648
  this.langBind("pagination|last_title", (value) => {
14244
14649
  this.lastBut.setAttribute("aria-label", value);
14245
14650
  this.lastBut.setAttribute("title", value);
14246
14651
  });
14247
-
14652
+
14248
14653
  //click bindings
14249
14654
  this.firstBut.addEventListener("click", () => {
14250
14655
  this.setPage(1);
14251
14656
  });
14252
-
14657
+
14253
14658
  this.prevBut.addEventListener("click", () => {
14254
14659
  this.previousPage();
14255
14660
  });
14256
-
14661
+
14257
14662
  this.nextBut.addEventListener("click", () => {
14258
14663
  this.nextPage();
14259
14664
  });
14260
-
14665
+
14261
14666
  this.lastBut.addEventListener("click", () => {
14262
14667
  this.setPage(this.max);
14263
14668
  });
14264
-
14669
+
14265
14670
  if(this.table.options.paginationElement){
14266
14671
  this.element = this.table.options.paginationElement;
14267
14672
  }
14268
-
14673
+
14269
14674
  if(this.pageSizeSelect){
14270
14675
  pageSelectLabel = document.createElement("label");
14271
-
14676
+
14272
14677
  this.langBind("pagination|page_size", (value) => {
14273
14678
  this.pageSizeSelect.setAttribute("aria-label", value);
14274
14679
  this.pageSizeSelect.setAttribute("title", value);
14275
14680
  pageSelectLabel.innerHTML = value;
14276
14681
  });
14277
-
14682
+
14278
14683
  this.element.appendChild(pageSelectLabel);
14279
14684
  this.element.appendChild(this.pageSizeSelect);
14280
-
14685
+
14281
14686
  this.pageSizeSelect.addEventListener("change", (e) => {
14282
14687
  this.setPageSize(this.pageSizeSelect.value == "true" ? true : this.pageSizeSelect.value);
14283
14688
  this.setPage(1);
14284
14689
  });
14285
14690
  }
14286
-
14691
+
14287
14692
  //append to DOM
14288
14693
  this.element.appendChild(this.firstBut);
14289
14694
  this.element.appendChild(this.prevBut);
14290
14695
  this.element.appendChild(this.pagesElement);
14291
14696
  this.element.appendChild(this.nextBut);
14292
14697
  this.element.appendChild(this.lastBut);
14293
-
14698
+
14294
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
+
14295
14720
  this.table.footerManager.append(this.element, this);
14296
14721
  }
14297
-
14722
+
14298
14723
  this.page = this.table.options.paginationInitialPage;
14299
14724
  this.count = this.table.options.paginationButtonCount;
14300
14725
  }
14301
-
14726
+
14302
14727
  //set default values
14303
14728
  this.mode = this.table.options.paginationMode;
14304
14729
  }
14305
-
14730
+
14306
14731
  initializeProgressive(mode){
14307
14732
  this.initializePaginator(true);
14308
14733
  this.mode = "progressive_" + mode;
14309
14734
  this.progressiveLoad = true;
14310
14735
  }
14311
-
14736
+
14312
14737
  trackChanges(){
14313
14738
  this.dispatch("page-changed");
14314
14739
  }
14315
-
14740
+
14316
14741
  setDisplayIndex(index){
14317
14742
  this.displayIndex = index;
14318
14743
  }
14319
-
14744
+
14320
14745
  getDisplayIndex(){
14321
14746
  return this.displayIndex;
14322
14747
  }
14323
-
14748
+
14324
14749
  //calculate maximum page from number of rows
14325
14750
  setMaxRows(rowCount){
14326
14751
  if(!rowCount){
@@ -14328,12 +14753,12 @@ class Page extends Module{
14328
14753
  }else {
14329
14754
  this.max = this.size === true ? 1 : Math.ceil(rowCount/this.size);
14330
14755
  }
14331
-
14756
+
14332
14757
  if(this.page > this.max){
14333
14758
  this.page = this.max;
14334
14759
  }
14335
14760
  }
14336
-
14761
+
14337
14762
  //reset to first page without triggering action
14338
14763
  reset(force){
14339
14764
  if(!this.initialLoad){
@@ -14342,91 +14767,128 @@ class Page extends Module{
14342
14767
  }
14343
14768
  }
14344
14769
  }
14345
-
14770
+
14346
14771
  //set the maximum page
14347
14772
  setMaxPage(max){
14348
-
14773
+
14349
14774
  max = parseInt(max);
14350
-
14775
+
14351
14776
  this.max = max || 1;
14352
-
14777
+
14353
14778
  if(this.page > this.max){
14354
14779
  this.page = this.max;
14355
14780
  this.trigger();
14356
14781
  }
14357
14782
  }
14358
-
14783
+
14359
14784
  //set current page number
14360
14785
  setPage(page){
14361
14786
  switch(page){
14362
14787
  case "first":
14363
14788
  return this.setPage(1);
14364
-
14789
+
14365
14790
  case "prev":
14366
14791
  return this.previousPage();
14367
-
14792
+
14368
14793
  case "next":
14369
14794
  return this.nextPage();
14370
-
14795
+
14371
14796
  case "last":
14372
14797
  return this.setPage(this.max);
14373
14798
  }
14374
-
14375
-
14799
+
14376
14800
  page = parseInt(page);
14377
-
14801
+
14378
14802
  if((page > 0 && page <= this.max) || this.mode !== "local"){
14379
14803
  this.page = page;
14380
-
14804
+
14381
14805
  this.trackChanges();
14382
-
14806
+
14383
14807
  return this.trigger();
14384
14808
  }else {
14385
14809
  console.warn("Pagination Error - Requested page is out of range of 1 - " + this.max + ":", page);
14386
14810
  return Promise.reject();
14387
14811
  }
14388
14812
  }
14389
-
14813
+
14390
14814
  setPageToRow(row){
14391
14815
  var rows = this.table.rowManager.getDisplayRows(this.displayIndex - 1);
14392
14816
  var index = rows.indexOf(row);
14393
-
14817
+
14394
14818
  if(index > -1){
14395
14819
  var page = this.size === true ? 1 : Math.ceil((index + 1) / this.size);
14396
-
14820
+
14397
14821
  return this.setPage(page)
14398
14822
  }else {
14399
14823
  console.warn("Pagination Error - Requested row is not visible");
14400
14824
  return Promise.reject();
14401
14825
  }
14402
14826
  }
14403
-
14827
+
14404
14828
  setPageSize(size){
14405
14829
  if(size !== true){
14406
14830
  size = parseInt(size);
14407
14831
  }
14408
-
14832
+
14409
14833
  if(size > 0){
14410
14834
  this.size = size;
14411
14835
  }
14412
-
14836
+
14413
14837
  if(this.pageSizeSelect){
14414
14838
  // this.pageSizeSelect.value = size;
14415
14839
  this.generatePageSizeSelectList();
14416
14840
  }
14417
-
14841
+
14418
14842
  this.trackChanges();
14419
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
+ }
14420
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
+
14421
14883
  //setup the pagination buttons
14422
14884
  _setPageButtons(){
14423
14885
  let leftSize = Math.floor((this.count-1) / 2);
14424
14886
  let rightSize = Math.ceil((this.count-1) / 2);
14425
14887
  let min = this.max - this.page + leftSize + 1 < this.count ? this.max-this.count+1: Math.max(this.page-leftSize,1);
14426
14888
  let max = this.page <= rightSize? Math.min(this.count, this.max) :Math.min(this.page+rightSize, this.max);
14427
-
14889
+
14428
14890
  while(this.pagesElement.firstChild) this.pagesElement.removeChild(this.pagesElement.firstChild);
14429
-
14891
+
14430
14892
  if(this.page == 1){
14431
14893
  this.firstBut.disabled = true;
14432
14894
  this.prevBut.disabled = true;
@@ -14434,7 +14896,7 @@ class Page extends Module{
14434
14896
  this.firstBut.disabled = false;
14435
14897
  this.prevBut.disabled = false;
14436
14898
  }
14437
-
14899
+
14438
14900
  if(this.page == this.max){
14439
14901
  this.lastBut.disabled = true;
14440
14902
  this.nextBut.disabled = true;
@@ -14442,66 +14904,66 @@ class Page extends Module{
14442
14904
  this.lastBut.disabled = false;
14443
14905
  this.nextBut.disabled = false;
14444
14906
  }
14445
-
14907
+
14446
14908
  for(let i = min; i <= max; i++){
14447
14909
  if(i>0 && i <= this.max){
14448
14910
  this.pagesElement.appendChild(this._generatePageButton(i));
14449
14911
  }
14450
14912
  }
14451
-
14913
+
14452
14914
  this.footerRedraw();
14453
14915
  }
14454
-
14916
+
14455
14917
  _generatePageButton(page){
14456
14918
  var button = document.createElement("button");
14457
-
14919
+
14458
14920
  button.classList.add("tabulator-page");
14459
14921
  if(page == this.page){
14460
14922
  button.classList.add("active");
14461
14923
  }
14462
-
14924
+
14463
14925
  button.setAttribute("type", "button");
14464
14926
  button.setAttribute("role", "button");
14465
-
14927
+
14466
14928
  this.langBind("pagination|page_title", (value) => {
14467
14929
  button.setAttribute("aria-label", value + " " + page);
14468
14930
  button.setAttribute("title", value + " " + page);
14469
14931
  });
14470
-
14932
+
14471
14933
  button.setAttribute("data-page", page);
14472
14934
  button.textContent = page;
14473
-
14935
+
14474
14936
  button.addEventListener("click", (e) => {
14475
14937
  this.setPage(page);
14476
14938
  });
14477
-
14939
+
14478
14940
  return button;
14479
14941
  }
14480
-
14942
+
14481
14943
  //previous page
14482
14944
  previousPage(){
14483
14945
  if(this.page > 1){
14484
14946
  this.page--;
14485
-
14947
+
14486
14948
  this.trackChanges();
14487
-
14949
+
14488
14950
  return this.trigger()
14489
-
14951
+
14490
14952
  }else {
14491
14953
  console.warn("Pagination Error - Previous page would be less than page 1:", 0);
14492
14954
  return Promise.reject();
14493
14955
  }
14494
14956
  }
14495
-
14957
+
14496
14958
  //next page
14497
14959
  nextPage(){
14498
14960
  if(this.page < this.max){
14499
14961
  this.page++;
14500
-
14962
+
14501
14963
  this.trackChanges();
14502
-
14964
+
14503
14965
  return this.trigger();
14504
-
14966
+
14505
14967
  }else {
14506
14968
  if(!this.progressiveLoad){
14507
14969
  console.warn("Pagination Error - Next page would be greater than maximum page of " + this.max + ":", this.max + 1);
@@ -14509,34 +14971,34 @@ class Page extends Module{
14509
14971
  return Promise.reject();
14510
14972
  }
14511
14973
  }
14512
-
14974
+
14513
14975
  //return current page number
14514
14976
  getPage(){
14515
14977
  return this.page;
14516
14978
  }
14517
-
14979
+
14518
14980
  //return max page number
14519
14981
  getPageMax(){
14520
14982
  return this.max;
14521
14983
  }
14522
-
14984
+
14523
14985
  getPageSize(size){
14524
14986
  return this.size;
14525
14987
  }
14526
-
14988
+
14527
14989
  getMode(){
14528
14990
  return this.mode;
14529
14991
  }
14530
-
14992
+
14531
14993
  //return appropriate rows for current page
14532
14994
  getRows(data){
14533
14995
  var output, start, end;
14534
-
14996
+
14535
14997
  if(this.mode == "local"){
14536
14998
  output = [];
14537
-
14999
+
14538
15000
  this.setMaxRows(data.length);
14539
-
15001
+
14540
15002
  if(this.size === true){
14541
15003
  start = 0;
14542
15004
  end = data.length;
@@ -14544,89 +15006,94 @@ class Page extends Module{
14544
15006
  start = this.size * (this.page - 1);
14545
15007
  end = start + parseInt(this.size);
14546
15008
  }
14547
-
14548
-
15009
+
15010
+
14549
15011
  this._setPageButtons();
14550
-
15012
+
14551
15013
  for(let i = start; i < end; i++){
14552
15014
  if(data[i]){
14553
15015
  output.push(data[i]);
14554
15016
  }
14555
15017
  }
14556
15018
 
15019
+ this._setPageCounter(data.length);
15020
+
14557
15021
  return output;
14558
15022
  }else {
14559
15023
  this._setPageButtons();
14560
-
15024
+ this._setPageCounter(data.length);
15025
+
14561
15026
  return data.slice(0);
14562
15027
  }
14563
15028
  }
14564
-
15029
+
14565
15030
  trigger(){
14566
15031
  var left;
14567
-
15032
+
14568
15033
  switch(this.mode){
14569
15034
  case "local":
14570
15035
  left = this.table.rowManager.scrollLeft;
14571
-
15036
+
14572
15037
  this.refreshData();
14573
15038
  this.table.rowManager.scrollHorizontal(left);
14574
-
15039
+
14575
15040
  this.dispatchExternal("pageLoaded", this.getPage());
14576
-
15041
+
14577
15042
  return Promise.resolve();
14578
-
15043
+
14579
15044
  case "remote":
14580
15045
  this.dataChanging = true;
14581
15046
  return this.reloadData(null)
14582
15047
  .finally(() => {
14583
15048
  this.dataChanging = false;
14584
15049
  })
14585
-
15050
+
14586
15051
  case "progressive_load":
14587
15052
  case "progressive_scroll":
14588
15053
  return this.reloadData(null, true);
14589
-
15054
+
14590
15055
  default:
14591
15056
  console.warn("Pagination Error - no such pagination mode:", this.mode);
14592
15057
  return Promise.reject();
14593
15058
  }
14594
15059
  }
14595
-
15060
+
14596
15061
  _parseRemoteData(data){
14597
15062
  var data, margin;
14598
-
15063
+
14599
15064
  if(typeof data.last_page === "undefined"){
14600
15065
  console.warn("Remote Pagination Error - Server response missing '" + (this.options("dataReceiveParams").last_page || "last_page") + "' property");
14601
15066
  }
14602
-
15067
+
14603
15068
  if(data.data){
14604
15069
  this.max = parseInt(data.last_page) || 1;
14605
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
+
14606
15073
  if(this.progressiveLoad){
14607
15074
  switch(this.mode){
14608
15075
  case "progressive_load":
14609
-
15076
+
14610
15077
  if(this.page == 1){
14611
15078
  this.table.rowManager.setData(data.data, false, this.page == 1);
14612
15079
  }else {
14613
15080
  this.table.rowManager.addRows(data.data);
14614
15081
  }
14615
-
15082
+
14616
15083
  if(this.page < this.max){
14617
15084
  setTimeout(() => {
14618
15085
  this.nextPage();
14619
15086
  }, this.table.options.progressiveLoadDelay);
14620
15087
  }
14621
15088
  break;
14622
-
15089
+
14623
15090
  case "progressive_scroll":
14624
15091
  data = this.page === 1 ? data.data : this.table.rowManager.getData().concat(data.data);
14625
-
15092
+
14626
15093
  this.table.rowManager.setData(data, this.page !== 1, this.page == 1);
14627
-
15094
+
14628
15095
  margin = this.table.options.progressiveLoadScrollMargin || (this.table.rowManager.element.clientHeight * 2);
14629
-
15096
+
14630
15097
  if(this.table.rowManager.element.scrollHeight <= (this.table.rowManager.element.clientHeight + margin)){
14631
15098
  setTimeout(() => {
14632
15099
  this.nextPage();
@@ -14634,7 +15101,7 @@ class Page extends Module{
14634
15101
  }
14635
15102
  break;
14636
15103
  }
14637
-
15104
+
14638
15105
  return false;
14639
15106
  }else {
14640
15107
  // left = this.table.rowManager.scrollLeft;
@@ -14642,23 +15109,23 @@ class Page extends Module{
14642
15109
  // this.table.rowManager.scrollHorizontal(left);
14643
15110
  // this.table.columnManager.scrollHorizontal(left);
14644
15111
  }
14645
-
15112
+
14646
15113
  }else {
14647
15114
  console.warn("Remote Pagination Error - Server response missing '" + (this.options("dataReceiveParams").data || "data") + "' property");
14648
15115
  }
14649
-
15116
+
14650
15117
  return data.data;
14651
15118
  }
14652
-
15119
+
14653
15120
  //handle the footer element being redrawn
14654
15121
  footerRedraw(){
14655
15122
  var footer = this.table.footerManager.element;
14656
-
15123
+
14657
15124
  if((Math.ceil(footer.clientWidth) - footer.scrollWidth) < 0){
14658
15125
  this.pagesElement.style.display = 'none';
14659
15126
  }else {
14660
15127
  this.pagesElement.style.display = '';
14661
-
15128
+
14662
15129
  if((Math.ceil(footer.clientWidth) - footer.scrollWidth) < 0){
14663
15130
  this.pagesElement.style.display = 'none';
14664
15131
  }
@@ -14666,7 +15133,10 @@ class Page extends Module{
14666
15133
  }
14667
15134
  }
14668
15135
 
14669
- Page.moduleName = "page";
15136
+ Page.moduleName = "page";
15137
+
15138
+ //load defaults
15139
+ Page.pageCounters = defaultPageCounters;
14670
15140
 
14671
15141
  // read peristence information from storage
14672
15142
  var defaultReaders = {
@@ -15898,7 +16368,7 @@ class ResizeRows extends Module{
15898
16368
 
15899
16369
  self.table.element.classList.remove("tabulator-block-select");
15900
16370
 
15901
- this.dispatchExternal("rowResized", row.getComponent());
16371
+ self.dispatchExternal("rowResized", row.getComponent());
15902
16372
  }
15903
16373
 
15904
16374
  e.stopPropagation(); //prevent resize from interfereing with movable columns
@@ -16901,8 +17371,8 @@ function datetime$1(a, b, aRow, bRow, column, dir, params){
16901
17371
  emptyAlign = 0;
16902
17372
 
16903
17373
  if(typeof DT != "undefined"){
16904
- a = DT.fromFormat(String(a), format);
16905
- b = DT.fromFormat(String(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);
16906
17376
 
16907
17377
  if(!a.isValid){
16908
17378
  emptyAlign = !b.isValid ? 0 : -1;
@@ -17678,7 +18148,7 @@ class Validate extends Module{
17678
18148
  columnValidate(column){
17679
18149
  var invalid = [];
17680
18150
 
17681
- column.cells.forEach(function(cell){
18151
+ column.cells.forEach((cell) => {
17682
18152
  if(!this.cellValidate(cell)){
17683
18153
  invalid.push(cell.getComponent());
17684
18154
  }
@@ -17694,7 +18164,7 @@ class Validate extends Module{
17694
18164
  rowValidate(row){
17695
18165
  var invalid = [];
17696
18166
 
17697
- row.cells.forEach(function(cell){
18167
+ row.cells.forEach((cell) => {
17698
18168
  if(!this.cellValidate(cell)){
17699
18169
  invalid.push(cell.getComponent());
17700
18170
  }
@@ -17726,7 +18196,9 @@ class Validate extends Module{
17726
18196
  var output = [];
17727
18197
 
17728
18198
  //clear row data
17729
- this.table.rowManager.rows.forEach(function(row){
18199
+ this.table.rowManager.rows.forEach((row) => {
18200
+ row = row.getComponent();
18201
+
17730
18202
  var valid = row.validate();
17731
18203
 
17732
18204
  if(valid !== true){
@@ -17756,7 +18228,7 @@ class Validate extends Module{
17756
18228
  if(column.definition.validator){
17757
18229
 
17758
18230
  if(Array.isArray(column.definition.validator)){
17759
- column.definition.validator.forEach(function(item){
18231
+ column.definition.validator.forEach((item) => {
17760
18232
  validator = self._extractValidator(item);
17761
18233
 
17762
18234
  if(validator){
@@ -17822,7 +18294,7 @@ class Validate extends Module{
17822
18294
  invalidIndex = this.invalidCells.indexOf(cell);
17823
18295
 
17824
18296
  if(validators){
17825
- validators.forEach(function(item){
18297
+ validators.forEach((item) => {
17826
18298
  if(!item.func.call(self, cell.getComponent(), value, item.params)){
17827
18299
  valid.push({
17828
18300
  type:item.type,
@@ -17909,6 +18381,7 @@ var modules = /*#__PURE__*/Object.freeze({
17909
18381
  GroupRowsModule: GroupRows,
17910
18382
  HistoryModule: History,
17911
18383
  HtmlTableImportModule: HtmlTableImport,
18384
+ ImportModule: Import,
17912
18385
  InteractionModule: Interaction,
17913
18386
  KeybindingsModule: Keybindings,
17914
18387
  MenuModule: Menu,
@@ -17938,7 +18411,6 @@ var defaultOptions = {
17938
18411
  minHeight:false, //minimum height of tabulator
17939
18412
  maxHeight:false, //maximum height of tabulator
17940
18413
 
17941
- columnMaxWidth:false, //minimum global width for a column
17942
18414
  columnHeaderVertAlign:"top", //vertical alignment of column headers
17943
18415
 
17944
18416
  columns:[],//store for colum header info
@@ -17983,6 +18455,7 @@ var defaultOptions = {
17983
18455
  dataLoader:true,
17984
18456
  dataLoaderLoading:false,
17985
18457
  dataLoaderError:false,
18458
+ dataLoaderErrorTimeout:3000,
17986
18459
 
17987
18460
  dataSendParams:{},
17988
18461
 
@@ -18272,10 +18745,10 @@ class VirtualDomHorizontal extends Renderer{
18272
18745
  }
18273
18746
 
18274
18747
  initialize(){
18275
- this.compatabilityCheck();
18748
+ this.compatibilityCheck();
18276
18749
  }
18277
18750
 
18278
- compatabilityCheck(){
18751
+ compatibilityCheck(){
18279
18752
  var columns = this.options("columns"),
18280
18753
  frozen = false,
18281
18754
  ok = true;
@@ -18361,7 +18834,7 @@ class VirtualDomHorizontal extends Renderer{
18361
18834
  config.width = width;
18362
18835
 
18363
18836
  if (this.options("layout") === "fitData") {
18364
- config.fitDataCheck = true;
18837
+ config.fitDataCheck = column.modules.vdomHoz ? column.modules.vdomHoz.fitDataCheck : true;
18365
18838
  }
18366
18839
 
18367
18840
  if((colPos + width > this.vDomScrollPosLeft) && (colPos < this.vDomScrollPosRight)){
@@ -18574,7 +19047,7 @@ class VirtualDomHorizontal extends Renderer{
18574
19047
 
18575
19048
  this.fitDataColActualWidthCheck(column);
18576
19049
 
18577
- this.rightCol++;
19050
+ this.rightCol++; // Don't move this below the >= check below
18578
19051
 
18579
19052
  if(this.rightCol >= (this.columns.length - 1)){
18580
19053
  this.vDomPadRight = 0;
@@ -18605,7 +19078,9 @@ class VirtualDomHorizontal extends Renderer{
18605
19078
 
18606
19079
  this.fitDataColActualWidthCheck(column);
18607
19080
 
18608
- if(!this.leftCol){
19081
+ this.leftCol--; // don't move this below the <= check below
19082
+
19083
+ if(this.leftCol <= 0){ // replicating logic in addColRight
18609
19084
  this.vDomPadLeft = 0;
18610
19085
  }else {
18611
19086
  this.vDomPadLeft -= column.getWidth();
@@ -18613,7 +19088,6 @@ class VirtualDomHorizontal extends Renderer{
18613
19088
 
18614
19089
  this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
18615
19090
 
18616
- this.leftCol--;
18617
19091
 
18618
19092
  this.addColLeft();
18619
19093
  }
@@ -18631,7 +19105,11 @@ class VirtualDomHorizontal extends Renderer{
18631
19105
  rows.forEach((row) => {
18632
19106
  if(row.type !== "group"){
18633
19107
  var cell = row.getCell(column);
18634
- 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
+ }
18635
19113
  }
18636
19114
  });
18637
19115
 
@@ -18661,7 +19139,11 @@ class VirtualDomHorizontal extends Renderer{
18661
19139
  el = cell.getElement();
18662
19140
 
18663
19141
  if(el.parentNode){
18664
- row.getElement().removeChild(el);
19142
+ try {
19143
+ row.getElement().removeChild(el);
19144
+ } catch (ex) {
19145
+ console.warn("Could not removeColLeft", ex.message);
19146
+ }
18665
19147
  }
18666
19148
  }
18667
19149
  }
@@ -19444,7 +19926,8 @@ class BaiscVertical extends Renderer{
19444
19926
 
19445
19927
 
19446
19928
  rerenderRows(callback){
19447
- this.render();
19929
+ this.clearRows();
19930
+ this.renderRows();
19448
19931
 
19449
19932
  if(callback){
19450
19933
  callback();
@@ -20052,7 +20535,7 @@ class RowManager extends CoreFeature{
20052
20535
  this.fixedHeight = false; //current rendering mode
20053
20536
 
20054
20537
  this.rows = []; //hold row data objects
20055
- this.activeRowsPipeline = []; //hold caluclation of active rows
20538
+ this.activeRowsPipeline = []; //hold calculation of active rows
20056
20539
  this.activeRows = []; //rows currently available to on display in the table
20057
20540
  this.activeRowsCount = 0; //count of active rows
20058
20541
 
@@ -20064,9 +20547,9 @@ class RowManager extends CoreFeature{
20064
20547
 
20065
20548
  this.rowNumColumn = false; //hold column component for row number column
20066
20549
 
20067
- 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
20068
20551
  this.redrawBlockRestoreConfig = false; //store latest redraw function calls for when redraw is needed
20069
- 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
20070
20553
 
20071
20554
  this.dataPipeline = []; //hold data pipeline tasks
20072
20555
  this.displayPipeline = []; //hold data display pipeline tasks
@@ -20737,7 +21220,7 @@ class RowManager extends CoreFeature{
20737
21220
  }
20738
21221
  }
20739
21222
 
20740
- this.dispatch("data-refeshed");
21223
+ this.dispatch("data-refreshed");
20741
21224
  }
20742
21225
  }
20743
21226
 
@@ -20849,7 +21332,7 @@ class RowManager extends CoreFeature{
20849
21332
  if(callback){
20850
21333
  callback();
20851
21334
  }else {
20852
- this.redrawBlockRederInPosition = true;
21335
+ this.redrawBlockRenderInPosition = true;
20853
21336
  }
20854
21337
  }else {
20855
21338
  this.renderer.rerenderRows(callback);
@@ -21028,12 +21511,12 @@ class RowManager extends CoreFeature{
21028
21511
 
21029
21512
  this.redrawBlockRestoreConfig = false;
21030
21513
  }else {
21031
- if(this.redrawBlockRederInPosition){
21514
+ if(this.redrawBlockRenderInPosition){
21032
21515
  this.reRenderInPosition();
21033
21516
  }
21034
21517
  }
21035
21518
 
21036
- this.redrawBlockRederInPosition = false;
21519
+ this.redrawBlockRenderInPosition = false;
21037
21520
  }
21038
21521
 
21039
21522
  //redraw table
@@ -21415,7 +21898,7 @@ class InteractionManager extends CoreFeature {
21415
21898
  switch(key){
21416
21899
  case "row":
21417
21900
  case "group":
21418
- if(listener.components.includes("row") || listener.components.includes("cell")){
21901
+ if(listener.components.includes("row") || listener.components.includes("cell") || listener.components.includes("group")){
21419
21902
  let rows = this.table.rowManager.getVisibleRows(true);
21420
21903
 
21421
21904
  component = rows.find((row) => {
@@ -21432,7 +21915,11 @@ class InteractionManager extends CoreFeature {
21432
21915
 
21433
21916
  case "cell":
21434
21917
  if(listener.components.includes("cell")){
21435
- 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
+ }
21436
21923
  }
21437
21924
  break;
21438
21925
  }
@@ -21581,8 +22068,8 @@ class DataLoader extends CoreFeature{
21581
22068
 
21582
22069
  params = this.mapParams(params, this.table.options.dataSendParams);
21583
22070
 
21584
- var result = this.chain("data-load", [data, params, config, silent], Promise.resolve([]));
21585
-
22071
+ var result = this.chain("data-load", [data, params, config, silent], false, Promise.resolve([]));
22072
+
21586
22073
  return result.then((response) => {
21587
22074
  if(!Array.isArray(response) && typeof response == "object"){
21588
22075
  response = this.mapParams(response, this.objectInvert(this.table.options.dataReceiveParams));
@@ -21607,10 +22094,10 @@ class DataLoader extends CoreFeature{
21607
22094
  if(!silent){
21608
22095
  this.showError();
21609
22096
  }
21610
-
22097
+
21611
22098
  setTimeout(() => {
21612
22099
  this.hideLoader();
21613
- }, 3000);
22100
+ }, this.table.options.dataLoaderErrorTimeout);
21614
22101
  })
21615
22102
  .finally(() => {
21616
22103
  this.loading = false;
@@ -22337,6 +22824,12 @@ var defaultLangs = {
22337
22824
  "next":"Next",
22338
22825
  "next_title":"Next Page",
22339
22826
  "all":"All",
22827
+ "counter":{
22828
+ "showing": "Showing",
22829
+ "of": "of",
22830
+ "rows": "rows",
22831
+ "pages": "pages",
22832
+ }
22340
22833
  },
22341
22834
  "headerFilters":{
22342
22835
  "default":"filter column...",
@@ -22994,49 +23487,6 @@ class Tabulator {
22994
23487
  return this.rowManager.restoreRedraw();
22995
23488
  }
22996
23489
 
22997
- //local data from local file
22998
- setDataFromLocalFile(extensions){
22999
- return new Promise((resolve, reject) => {
23000
- var input = document.createElement("input");
23001
- input.type = "file";
23002
- input.accept = extensions || ".json,application/json";
23003
-
23004
- input.addEventListener("change", (e) => {
23005
- var file = input.files[0],
23006
- reader = new FileReader(),
23007
- data;
23008
-
23009
- reader.readAsText(file);
23010
-
23011
- reader.onload = (e) => {
23012
-
23013
- try {
23014
- data = JSON.parse(reader.result);
23015
- } catch(e) {
23016
- console.warn("File Load Error - File contents is invalid JSON", e);
23017
- reject(e);
23018
- return;
23019
- }
23020
-
23021
- this.setData(data)
23022
- .then((data) => {
23023
- resolve(data);
23024
- })
23025
- .catch((err) => {
23026
- resolve(err);
23027
- });
23028
- };
23029
-
23030
- reader.onerror = (e) => {
23031
- console.warn("File Load Error - Unable to read file");
23032
- reject();
23033
- };
23034
- });
23035
-
23036
- input.click();
23037
- });
23038
- }
23039
-
23040
23490
  //load data
23041
23491
  setData(data, params, config){
23042
23492
  if(this.initialized){
@@ -23585,5 +24035,5 @@ class PseudoRow {
23585
24035
  clearCellHeight(){}
23586
24036
  }
23587
24037
 
23588
- 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 };
23589
24039
  //# sourceMappingURL=tabulator_esm.js.map