tabulator-tables 5.0.8 → 5.1.1

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 (112) hide show
  1. package/.editorconfig +6 -0
  2. package/LICENSE +1 -1
  3. package/bower.json +1 -1
  4. package/build/rollup.js +2 -1
  5. package/dist/css/tabulator.css +26 -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 +26 -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 +26 -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 +26 -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 +33 -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 +30 -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 +26 -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 +26 -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 +26 -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 +30 -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 +1182 -548
  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 +1797 -1184
  50. package/dist/js/tabulator_esm.js.map +1 -1
  51. package/dist/js/tabulator_esm.min.js +2 -2
  52. package/dist/js/tabulator_esm.min.js.map +1 -1
  53. package/package.json +1 -1
  54. package/src/js/core/ColumnManager.js +1 -1
  55. package/src/js/core/CoreFeature.js +1 -5
  56. package/src/js/core/FooterManager.js +14 -2
  57. package/src/js/core/RowManager.js +325 -286
  58. package/src/js/core/Tabulator.js +0 -43
  59. package/src/js/core/cell/Cell.js +5 -1
  60. package/src/js/core/column/Column.js +21 -6
  61. package/src/js/core/column/ColumnComponent.js +6 -0
  62. package/src/js/core/column/defaults/options.js +1 -0
  63. package/src/js/core/defaults/options.js +3 -3
  64. package/src/js/core/modules/optional.js +1 -0
  65. package/src/js/core/rendering/Renderer.js +3 -2
  66. package/src/js/core/rendering/renderers/BasicVertical.js +2 -1
  67. package/src/js/core/rendering/renderers/VirtualDomHorizontal.js +165 -151
  68. package/src/js/core/rendering/renderers/VirtualDomVertical.js +1 -1
  69. package/src/js/core/row/Row.js +2 -2
  70. package/src/js/core/tools/DataLoader.js +6 -6
  71. package/src/js/core/tools/InteractionMonitor.js +157 -52
  72. package/src/js/modules/Ajax/Ajax.js +62 -82
  73. package/src/js/modules/ColumnCalcs/ColumnCalcs.js +16 -3
  74. package/src/js/modules/DataTree/DataTree.js +22 -9
  75. package/src/js/modules/Download/defaults/downloaders/json.js +1 -1
  76. package/src/js/modules/Download/defaults/downloaders/jsonLines.js +32 -0
  77. package/src/js/modules/Download/defaults/downloaders/pdf.js +0 -2
  78. package/src/js/modules/Download/defaults/downloaders/xlsx.js +3 -2
  79. package/src/js/modules/Download/defaults/downloaders.js +2 -0
  80. package/src/js/modules/Edit/Edit.js +27 -39
  81. package/src/js/modules/Export/Export.js +1 -1
  82. package/src/js/modules/Filter/Filter.js +1 -1
  83. package/src/js/modules/Format/defaults/formatters/datetime.js +1 -1
  84. package/src/js/modules/Format/defaults/formatters/datetimediff.js +2 -1
  85. package/src/js/modules/FrozenColumns/FrozenColumns.js +1 -1
  86. package/src/js/modules/FrozenRows/FrozenRows.js +9 -0
  87. package/src/js/modules/GroupRows/Group.js +8 -63
  88. package/src/js/modules/GroupRows/GroupComponent.js +1 -1
  89. package/src/js/modules/GroupRows/GroupRows.js +2 -2
  90. package/src/js/modules/Import/Import.js +195 -0
  91. package/src/js/modules/Import/defaults/importers/csv.js +63 -0
  92. package/src/js/modules/Import/defaults/importers/json.js +8 -0
  93. package/src/js/modules/Import/defaults/importers.js +7 -0
  94. package/src/js/modules/Interaction/Interaction.js +5 -0
  95. package/src/js/modules/Keybindings/Keybindings.js +9 -14
  96. package/src/js/modules/Keybindings/defaults/bindings.js +3 -3
  97. package/src/js/modules/Localize/defaults/langs.js +6 -0
  98. package/src/js/modules/Menu/Menu.js +200 -155
  99. package/src/js/modules/MoveRows/MoveRows.js +4 -0
  100. package/src/js/modules/Page/Page.js +282 -185
  101. package/src/js/modules/Page/defaults/pageCounters/pages.js +33 -0
  102. package/src/js/modules/Page/defaults/pageCounters/rows.js +32 -0
  103. package/src/js/modules/Page/defaults/pageCounters.js +8 -0
  104. package/src/js/modules/ResizeRows/ResizeRows.js +1 -1
  105. package/src/js/modules/ResponsiveLayout/ResponsiveLayout.js +7 -9
  106. package/src/js/modules/SelectRow/SelectRow.js +4 -9
  107. package/src/js/modules/Sort/defaults/sorters/datetime.js +2 -2
  108. package/src/js/modules/Validate/Validate.js +7 -5
  109. package/src/scss/tabulator.scss +31 -8
  110. package/src/scss/themes/materialize/tabulator_materialize.scss +5 -4
  111. package/src/scss/themes/tabulator_midnight.scss +4 -0
  112. package/src/scss/themes/tabulator_site.scss +4 -0
@@ -1,75 +1,149 @@
1
1
  import CoreFeature from '../CoreFeature.js';
2
2
  import Helpers from './Helpers.js';
3
+ import Row from '../row/Row.js';
3
4
 
4
5
  export default class InteractionManager extends CoreFeature {
5
-
6
+
6
7
  constructor (table){
7
8
  super(table);
8
-
9
+
9
10
  this.el = null;
10
-
11
+
11
12
  this.abortClasses = ["tabulator-headers", "tabulator-table"];
12
-
13
+
13
14
  this.previousTargets = {};
14
-
15
+
15
16
  this.listeners = [
16
- "click",
17
- "dblclick",
18
- "contextmenu",
19
- "mouseenter",
20
- "mouseleave",
21
- "mouseover",
22
- "mouseout",
23
- "mousemove",
24
- "touchstart",
25
- "touchend",
17
+ "click",
18
+ "dblclick",
19
+ "contextmenu",
20
+ "mouseenter",
21
+ "mouseleave",
22
+ "mouseover",
23
+ "mouseout",
24
+ "mousemove",
25
+ "touchstart",
26
+ "touchend",
26
27
  ];
27
-
28
+
28
29
  this.componentMap = {
29
30
  "tabulator-cell":"cell",
30
31
  "tabulator-row":"row",
31
32
  "tabulator-group":"group",
32
33
  "tabulator-col":"column",
33
34
  };
35
+
36
+ this.pseudoTrackers = {
37
+ "row":{
38
+ subscriber:null,
39
+ target:null,
40
+ },
41
+ "cell":{
42
+ subscriber:null,
43
+ target:null,
44
+ },
45
+ "group":{
46
+ subscriber:null,
47
+ target:null,
48
+ },
49
+ "column":{
50
+ subscriber:null,
51
+ target:null,
52
+ },
53
+ }
54
+
55
+ this.pseudoTracking = false;
34
56
  }
35
-
57
+
36
58
  initialize(){
37
59
  this.el = this.table.element;
60
+
38
61
  this.buildListenerMap();
39
62
  this.bindSubscriptionWatchers();
40
63
  }
41
-
64
+
42
65
  buildListenerMap(){
43
66
  var listenerMap = {};
44
-
67
+
45
68
  this.listeners.forEach((listener) => {
46
69
  listenerMap[listener] = {
47
70
  handler:null,
48
71
  components:[],
49
72
  }
50
73
  })
51
-
74
+
52
75
  this.listeners = listenerMap;
53
76
  }
54
-
77
+
78
+ bindPseudoEvents(){
79
+ Object.keys(this.pseudoTrackers).forEach((key) => {
80
+ this.pseudoTrackers[key].subscriber = this.pseudoMouseEnter.bind(this, key);
81
+ this.subscribe(key + "-mouseover", this.pseudoTrackers[key].subscriber);
82
+ });
83
+
84
+ this.pseudoTracking = true;
85
+ }
86
+
87
+ pseudoMouseEnter(key, e, target){
88
+ if(this.pseudoTrackers[key].target !== target){
89
+
90
+ if(this.pseudoTrackers[key].target){
91
+ this.dispatch(key + "-mouseleave", e, target);
92
+ }
93
+
94
+ this.pseudoMouseLeave(key, e);
95
+
96
+ this.pseudoTrackers[key].target = target;
97
+
98
+ this.dispatch(key + "-mouseenter", e, target);
99
+ }
100
+ }
101
+
102
+ pseudoMouseLeave(key, e){
103
+ var leaveList = Object.keys(this.pseudoTrackers),
104
+ linkedKeys = {
105
+ "row":["cell"],
106
+ "cell":["row"],
107
+ };
108
+
109
+ leaveList = leaveList.filter((item) => {
110
+ var links = linkedKeys[key];
111
+ return item !== key && (!links || (links && !links.includes(item)));
112
+ });
113
+
114
+
115
+ leaveList.forEach((key) => {
116
+ var target = this.pseudoTrackers[key].target;
117
+
118
+ if(this.pseudoTrackers[key].target){
119
+ this.dispatch(key + "-mouseleave", e, target);
120
+
121
+ this.pseudoTrackers[key].target = null;
122
+ }
123
+ });
124
+ }
125
+
126
+
55
127
  bindSubscriptionWatchers(){
56
128
  var listeners = Object.keys(this.listeners),
57
129
  components = Object.values(this.componentMap);
58
-
130
+
59
131
  for(let comp of components){
60
132
  for(let listener of listeners){
61
133
  let key = comp + "-" + listener;
62
-
134
+
63
135
  this.subscriptionChange(key, this.subscriptionChanged.bind(this, comp, listener));
64
136
  }
65
137
  }
138
+
139
+ this.subscribe("table-destroy", this.clearWatchers.bind(this))
66
140
  }
67
-
141
+
68
142
  subscriptionChanged(component, key, added){
69
143
  var listener = this.listeners[key].components,
70
144
  index = listener.indexOf(component),
71
145
  changed = false;
72
-
146
+
73
147
  if(added){
74
148
  if(index === -1){
75
149
  listener.push(component);
@@ -83,16 +157,20 @@ export default class InteractionManager extends CoreFeature {
83
157
  }
84
158
  }
85
159
  }
86
-
160
+
161
+ if((key === "mouseenter" || key === "mouseleave") && !this.pseudoTracking){
162
+ this.bindPseudoEvents();
163
+ }
164
+
87
165
  if(changed){
88
166
  this.updateEventListeners();
89
167
  }
90
168
  }
91
-
169
+
92
170
  updateEventListeners(){
93
171
  for(let key in this.listeners){
94
172
  let listener = this.listeners[key];
95
-
173
+
96
174
  if(listener.components.length){
97
175
  if(!listener.handler){
98
176
  listener.handler = this.track.bind(this, key);
@@ -107,86 +185,102 @@ export default class InteractionManager extends CoreFeature {
107
185
  }
108
186
  }
109
187
  }
110
-
188
+
111
189
  track(type, e){
112
190
  var path = (e.composedPath && e.composedPath()) || e.path;
191
+
113
192
  var targets = this.findTargets(path);
114
193
  targets = this.bindComponents(type, targets);
194
+
115
195
  this.triggerEvents(type, e, targets);
196
+
197
+ if(this.pseudoTracking && (type == "mouseover" || type == "mouseleave") && !Object.keys(targets).length){
198
+ this.pseudoMouseLeave("none", e);
199
+ }
116
200
  }
117
-
201
+
118
202
  findTargets(path){
119
203
  var targets = {};
120
-
204
+
121
205
  let componentMap = Object.keys(this.componentMap);
122
-
206
+
123
207
  for (let el of path) {
124
208
  let classList = el.classList ? [...el.classList] : [];
125
-
209
+
126
210
  let abort = classList.filter((item) => {
127
211
  return this.abortClasses.includes(item);
128
212
  })
129
-
213
+
130
214
  if(abort.length){
131
215
  break;
132
216
  }
133
-
217
+
134
218
  let elTargets = classList.filter((item) => {
135
219
  return componentMap.includes(item);
136
220
  })
137
-
221
+
138
222
  for (let target of elTargets) {
139
223
  targets[this.componentMap[target]] = el;
140
224
  }
141
225
  }
142
-
226
+
143
227
  if(targets.group && targets.group === targets.row){
144
228
  delete targets.row;
145
229
  }
146
-
230
+
147
231
  return targets;
148
232
  }
149
-
233
+
150
234
  bindComponents(type, targets){
151
235
  //ensure row component is looked up before cell
152
236
  var keys = Object.keys(targets).reverse(),
153
237
  listener = this.listeners[type],
154
238
  targetMatches = {};
155
-
239
+
156
240
  for(let key of keys){
157
241
  let component;
158
242
  let target = targets[key];
159
243
  let previousTarget = this.previousTargets[key];
160
-
244
+
161
245
  if(previousTarget && previousTarget.target === target){
162
246
  component = previousTarget.component;
163
247
  }else{
164
248
  switch(key){
165
249
  case "row":
166
250
  case "group":
167
- if(listener.components.includes("row") || listener.components.includes("cell")){
168
- let rows = this.table.rowManager.getVisibleRows();
169
-
251
+ if(listener.components.includes("row") || listener.components.includes("cell") || listener.components.includes("group")){
252
+ let rows = this.table.rowManager.getVisibleRows(true);
253
+
170
254
  component = rows.find((row) => {
171
255
  return row.getElement() === target;
172
256
  });
257
+
258
+ if(targets["row"].parentNode && targets["row"].parentNode.closest(".tabulator-row")){
259
+ targets[key] = false;
260
+ }
173
261
  }
174
262
  break;
175
-
263
+
176
264
  case "column":
177
265
  if(listener.components.includes("column")){
178
266
  component = this.table.columnManager.findColumn(target);
179
267
  }
180
268
  break
181
-
269
+
182
270
  case "cell":
183
271
  if(listener.components.includes("cell")){
184
- component = targets["row"].findCell(target);
272
+ if(targets["row"] instanceof Row){
273
+ component = targets["row"].findCell(target);
274
+ }else{
275
+ if(targets["row"]){
276
+ 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?")
277
+ }
278
+ }
185
279
  }
186
280
  break;
187
281
  }
188
282
  }
189
-
283
+
190
284
  if(component){
191
285
  targets[key] = component;
192
286
  targetMatches[key] = {
@@ -195,19 +289,30 @@ export default class InteractionManager extends CoreFeature {
195
289
  }
196
290
  }
197
291
  }
198
-
292
+
199
293
  this.previousTargets = targetMatches;
200
-
294
+
201
295
  return targets;
202
296
  }
203
-
297
+
204
298
  triggerEvents(type, e, targets){
205
299
  var listener = this.listeners[type];
206
-
300
+
207
301
  for(let key in targets){
208
302
  if(targets[key] && listener.components.includes(key)){
209
303
  this.dispatch(key + "-" + type, e, targets[key]);
210
304
  }
211
305
  }
212
306
  }
307
+
308
+ clearWatchers(){
309
+ for(let key in this.listeners){
310
+ let listener = this.listeners[key];
311
+
312
+ if(listener.handler){
313
+ this.el.removeEventListener(key, listener.handler)
314
+ listener.handler = null;
315
+ }
316
+ }
317
+ }
213
318
  }
@@ -6,145 +6,125 @@ import defaultLoaderPromise from './defaults/loaderPromise.js';
6
6
  import defaultContentTypeFormatters from './defaults/contentTypeFormatters.js';
7
7
 
8
8
  class Ajax extends Module{
9
-
9
+
10
10
  constructor(table){
11
11
  super(table);
12
-
13
- this.config = false; //hold config object for ajax request
12
+
13
+ this.config = {}; //hold config object for ajax request
14
14
  this.url = ""; //request URL
15
15
  this.urlGenerator = false;
16
16
  this.params = false; //request parameters
17
-
17
+
18
18
  this.loaderPromise = false;
19
-
19
+
20
20
  this.registerTableOption("ajaxURL", false); //url for ajax loading
21
21
  this.registerTableOption("ajaxURLGenerator", false);
22
22
  this.registerTableOption("ajaxParams", {}); //params for ajax loading
23
23
  this.registerTableOption("ajaxConfig", "get"); //ajax request type
24
24
  this.registerTableOption("ajaxContentType", "form"); //ajax request type
25
25
  this.registerTableOption("ajaxRequestFunc", false); //promise function
26
-
26
+
27
27
  this.registerTableOption("ajaxRequesting", function(){});
28
28
  this.registerTableOption("ajaxResponse", false);
29
-
29
+
30
30
  this.contentTypeFormatters = Ajax.contentTypeFormatters;
31
31
  }
32
-
32
+
33
33
  //initialize setup options
34
34
  initialize(){
35
35
  this.loaderPromise = this.table.options.ajaxRequestFunc || Ajax.defaultLoaderPromise;
36
36
  this.urlGenerator = this.table.options.ajaxURLGenerator || Ajax.defaultURLGenerator;
37
-
38
- if(this.table.options.ajaxParams){
39
- this.setParams(this.table.options.ajaxParams);
40
- }
41
-
42
- if(this.table.options.ajaxConfig){
43
- this.setConfig(this.table.options.ajaxConfig);
44
- }
45
-
37
+
46
38
  if(this.table.options.ajaxURL){
47
39
  this.setUrl(this.table.options.ajaxURL);
48
40
  }
49
41
 
50
- this.registerTableFunction("getAjaxUrl", this.getUrl.bind(this));
51
42
 
43
+ this.setDefaultConfig(this.table.options.ajaxConfig);
44
+
45
+ this.registerTableFunction("getAjaxUrl", this.getUrl.bind(this));
46
+
52
47
  this.subscribe("data-loading", this.requestDataCheck.bind(this));
48
+ this.subscribe("data-params", this.requestParams.bind(this));
53
49
  this.subscribe("data-load", this.requestData.bind(this));
54
50
  }
55
-
56
-
51
+
52
+ requestParams(data, config, silent, params){
53
+ var ajaxParams = this.table.options.ajaxParams;
54
+
55
+ if(ajaxParams){
56
+ if(typeof ajaxParams === "function"){
57
+ ajaxParams = ajaxParams.call(this.table);
58
+ }
59
+
60
+ params = Object.assign(params, ajaxParams);
61
+ }
62
+
63
+ return params;
64
+ }
65
+
57
66
  requestDataCheck(data, params, config, silent){
58
67
  return !!((!data && this.url) || typeof data === "string");
59
68
  }
60
-
61
- requestData(data, params, config, silent, previousData){
62
- if(this.requestDataCheck(data)){
63
- if(data){
64
- this.setUrl(data);
65
- }
66
-
67
- if(params){
68
- this.setParams(params, true);
69
- }
70
-
71
- if(config){
72
- this.setConfig(config);
69
+
70
+ requestData(url, params, config, silent, previousData){
71
+ var ajaxConfig;
72
+
73
+ if(!previousData && this.requestDataCheck(url)){
74
+ if(url){
75
+ this.setUrl(url);
73
76
  }
74
-
75
- return this.sendRequest();
77
+
78
+ ajaxConfig = this.generateConfig(config);
79
+
80
+ return this.sendRequest(this.url, params, ajaxConfig);
76
81
  }else{
77
82
  return previousData;
78
83
  }
79
84
  }
85
+
86
+ setDefaultConfig(config = {}){
87
+ this.config = Object.assign({}, Ajax.defaultConfig);
80
88
 
81
- //set ajax params
82
- setParams(params, update){
83
- if(update){
84
- this.params = this.params || {};
85
-
86
- for(let key in params){
87
- this.params[key] = params[key];
88
- }
89
+ if(typeof config == "string"){
90
+ this.config.method = config;
89
91
  }else{
90
- this.params = params;
92
+ Object.assign(this.config, config);
91
93
  }
92
94
  }
93
-
94
- getParams(){
95
- return this.params || {};
96
- }
97
-
95
+
98
96
  //load config object
99
- setConfig(config){
100
- this._loadDefaultConfig();
101
-
97
+ generateConfig(config = {}){
98
+ var ajaxConfig = Object.assign({}, this.config)
99
+
102
100
  if(typeof config == "string"){
103
- this.config.method = config;
101
+ ajaxConfig.method = config;
104
102
  }else{
105
- for(let key in config){
106
- this.config[key] = config[key];
107
- }
103
+ Object.assign(ajaxConfig, config);
108
104
  }
105
+
106
+ return ajaxConfig;
109
107
  }
110
-
111
- //create config object from default
112
- _loadDefaultConfig(force){
113
- if(!this.config || force){
114
-
115
- this.config = {};
116
-
117
- //load base config from defaults
118
- for(let key in Ajax.defaultConfig){
119
- this.config[key] = Ajax.defaultConfig[key];
120
- }
121
- }
122
- }
123
-
108
+
124
109
  //set request url
125
110
  setUrl(url){
126
111
  this.url = url;
127
112
  }
128
-
113
+
129
114
  //get request url
130
115
  getUrl(){
131
116
  return this.url;
132
117
  }
133
-
118
+
134
119
  //send ajax request
135
- sendRequest(silent){
136
- var url = this.url,
137
- esc, query;
138
-
139
- this._loadDefaultConfig();
140
-
141
- if(this.table.options.ajaxRequesting.call(this.table, this.url, this.params) !== false){
142
- return this.loaderPromise(url, this.config, this.params)
120
+ sendRequest(url, params, config){
121
+ if(this.table.options.ajaxRequesting.call(this.table, url, params) !== false){
122
+ return this.loaderPromise(url, config, params)
143
123
  .then((data)=>{
144
124
  if(this.table.options.ajaxResponse){
145
- data = this.table.options.ajaxResponse.call(this.table, this.url, this.params, data);
125
+ data = this.table.options.ajaxResponse.call(this.table, url, params, data);
146
126
  }
147
-
127
+
148
128
  return data;
149
129
  });
150
130
  }else{
@@ -51,8 +51,9 @@ class ColumnCalcs extends Module{
51
51
  this.subscribe("row-added", this.rowsUpdated.bind(this));
52
52
  this.subscribe("column-moved", this.recalcActiveRows.bind(this));
53
53
  this.subscribe("column-add", this.recalcActiveRows.bind(this));
54
- this.subscribe("data-refeshed", this.recalcActiveRows.bind(this));
54
+ this.subscribe("data-refreshed", this.recalcActiveRows.bind(this));
55
55
  this.subscribe("table-redraw", this.tableRedraw.bind(this));
56
+ this.subscribe("rows-visible", this.visibleRows.bind(this));
56
57
 
57
58
  this.registerTableFunction("getCalcResults", this.getResults.bind(this));
58
59
  this.registerTableFunction("recalc", this.userRecalc.bind(this));
@@ -78,6 +79,18 @@ class ColumnCalcs extends Module{
78
79
  ///////// Internal Logic //////////
79
80
  ///////////////////////////////////
80
81
 
82
+ visibleRows(viewable, rows){
83
+ if(this.topRow){
84
+ rows.unshift(this.topRow);
85
+ }
86
+
87
+ if(this.botRow){
88
+ rows.push(this.botRow);
89
+ }
90
+
91
+ return rows;
92
+ }
93
+
81
94
  rowsUpdated(row){
82
95
  if(this.table.options.groupBy){
83
96
  this.recalcRowGroup(this);
@@ -318,12 +331,12 @@ class ColumnCalcs extends Module{
318
331
 
319
332
  rowsToData(rows){
320
333
  var data = [];
321
-
334
+
322
335
  rows.forEach((row) => {
323
336
  data.push(row.getData());
324
337
 
325
338
  if(this.table.options.dataTree && this.table.options.dataTreeChildColumnCalcs){
326
- if(row.modules.dataTree.open){
339
+ if(row.modules.dataTree && row.modules.dataTree.open){
327
340
  var children = this.rowsToData(this.table.modules.dataTree.getFilteredTreeChildren(row));
328
341
  data = data.concat(children);
329
342
  }
@@ -38,17 +38,16 @@ class DataTree extends Module{
38
38
  this.registerComponentFunction("row", "getTreeParent", this.getTreeParent.bind(this));
39
39
  this.registerComponentFunction("row", "getTreeChildren", this.getRowChildren.bind(this));
40
40
  this.registerComponentFunction("row", "addTreeChild", this.addTreeChildRow.bind(this));
41
+ this.registerComponentFunction("row", "isTreeExpanded", this.isRowExpanded.bind(this));
41
42
  }
42
43
 
43
44
  initialize(){
44
45
  if(this.table.options.dataTree){
45
46
  var dummyEl = null,
46
- firstCol = this.table.columnManager.getFirstVisibileColumn(),
47
47
  options = this.table.options;
48
48
 
49
49
  this.field = options.dataTreeChildField;
50
50
  this.indent = options.dataTreeChildIndent;
51
- this.elementField = options.dataTreeElementColumn || (firstCol ? firstCol.field : false);
52
51
 
53
52
  if(options.dataTreeBranchElement){
54
53
 
@@ -117,15 +116,23 @@ class DataTree extends Module{
117
116
 
118
117
  this.subscribe("row-init", this.initializeRow.bind(this));
119
118
  this.subscribe("row-layout-after", this.layoutRow.bind(this));
120
- this.subscribe("row-relayout", this.layoutRow.bind(this));
121
119
  this.subscribe("row-deleted", this.rowDelete.bind(this),0);
122
120
  this.subscribe("row-data-changed", this.rowDataChanged.bind(this), 10);
121
+ this.subscribe("cell-value-updated", this.cellValueChanged.bind(this));
122
+ this.subscribe("edit-cancelled", this.cellValueChanged.bind(this));
123
123
  this.subscribe("column-moving-rows", this.columnMoving.bind(this));
124
+ this.subscribe("table-built", this.initializeElementField.bind(this));
124
125
 
125
126
  this.registerDisplayHandler(this.getRows.bind(this), 30);
126
127
  }
127
128
  }
128
129
 
130
+ initializeElementField(){
131
+ var firstCol = this.table.columnManager.getFirstVisibleColumn();
132
+
133
+ this.elementField = this.table.options.dataTreeElementColumn || (firstCol ? firstCol.field : false);
134
+ }
135
+
129
136
  getRowChildren(row){
130
137
  return this.getTreeChildren(row, true);
131
138
  }
@@ -151,6 +158,14 @@ class DataTree extends Module{
151
158
  }
152
159
  }
153
160
 
161
+ cellValueChanged(cell){
162
+ var field = cell.column.getField();
163
+
164
+ if(field === this.elementField){
165
+ this.layoutRow(cell.row);
166
+ }
167
+ }
168
+
154
169
  initializeRow(row){
155
170
  var childArray = row.getData()[this.field];
156
171
  var isArray = Array.isArray(childArray);
@@ -396,6 +411,10 @@ class DataTree extends Module{
396
411
  }
397
412
  }
398
413
 
414
+ isRowExpanded(row){
415
+ return row.modules.dataTree.open;
416
+ }
417
+
399
418
  getTreeParent(row){
400
419
  return row.modules.dataTree.parent ? row.modules.dataTree.parent.getComponent() : false;
401
420
  }
@@ -555,12 +574,6 @@ class DataTree extends Module{
555
574
  return output;
556
575
  }
557
576
 
558
- checkForRestyle(cell){
559
- if(!cell.row.cells.indexOf(cell)){
560
- this.layoutRow(cell.row);
561
- }
562
- }
563
-
564
577
  getChildField(){
565
578
  return this.field;
566
579
  }
@@ -19,7 +19,7 @@ export default function(list, options, setFileContents){
19
19
  case "row":
20
20
  row.columns.forEach((col) => {
21
21
  if(col){
22
- item[col.component.getField()] = col.value;
22
+ item[col.component.getTitleDownload() || col.component.getField()] = col.value;
23
23
  }
24
24
  });
25
25