@refinitiv-ui/efx-grid 6.0.26 → 6.0.28

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. package/lib/core/dist/core.js +287 -34
  2. package/lib/core/dist/core.min.js +1 -1
  3. package/lib/core/es6/data/DataTable.d.ts +1 -1
  4. package/lib/core/es6/data/DataTable.js +3 -2
  5. package/lib/core/es6/data/DataView.d.ts +1 -1
  6. package/lib/core/es6/data/DataView.js +3 -2
  7. package/lib/core/es6/data/Segment.d.ts +1 -1
  8. package/lib/core/es6/data/Segment.js +12 -3
  9. package/lib/core/es6/data/SegmentCollection.d.ts +1 -1
  10. package/lib/core/es6/data/SegmentCollection.js +3 -2
  11. package/lib/core/es6/grid/Core.d.ts +17 -3
  12. package/lib/core/es6/grid/Core.js +226 -20
  13. package/lib/core/es6/grid/components/Scrollbar.js +6 -0
  14. package/lib/grid/index.js +1 -1
  15. package/lib/row-segmenting/es6/RowSegmenting.js +21 -2
  16. package/lib/rt-grid/dist/rt-grid.js +418 -238
  17. package/lib/rt-grid/dist/rt-grid.min.js +1 -1
  18. package/lib/rt-grid/es6/ColumnDefinition.d.ts +2 -2
  19. package/lib/rt-grid/es6/ColumnDefinition.js +71 -70
  20. package/lib/rt-grid/es6/Grid.d.ts +9 -2
  21. package/lib/rt-grid/es6/Grid.js +55 -132
  22. package/lib/tr-grid-column-grouping/es6/ColumnGrouping.d.ts +12 -2
  23. package/lib/tr-grid-column-grouping/es6/ColumnGrouping.js +138 -47
  24. package/lib/tr-grid-column-stack/es6/ColumnStack.d.ts +14 -1
  25. package/lib/tr-grid-column-stack/es6/ColumnStack.js +317 -187
  26. package/lib/tr-grid-range-bar/es6/RangeBar.d.ts +4 -0
  27. package/lib/tr-grid-range-bar/es6/RangeBar.js +8 -0
  28. package/lib/tr-grid-util/es6/GridPlugin.d.ts +6 -0
  29. package/lib/tr-grid-util/es6/GridPlugin.js +67 -0
  30. package/lib/tr-grid-util/es6/GroupDefinitions.d.ts +5 -1
  31. package/lib/tr-grid-util/es6/GroupDefinitions.js +34 -5
  32. package/lib/types/es6/ColumnGrouping.d.ts +12 -2
  33. package/lib/types/es6/ColumnStack.d.ts +14 -1
  34. package/lib/types/es6/Core/data/DataTable.d.ts +1 -1
  35. package/lib/types/es6/Core/data/DataView.d.ts +1 -1
  36. package/lib/types/es6/Core/data/Segment.d.ts +1 -1
  37. package/lib/types/es6/Core/data/SegmentCollection.d.ts +1 -1
  38. package/lib/types/es6/Core/grid/Core.d.ts +17 -3
  39. package/lib/types/es6/RealtimeGrid/ColumnDefinition.d.ts +2 -2
  40. package/lib/types/es6/RealtimeGrid/Grid.d.ts +9 -2
  41. package/lib/versions.json +5 -5
  42. package/package.json +1 -1
@@ -12,6 +12,7 @@ import { preventDefault } from "../../tr-grid-util/es6/EventDispatcher.js";
12
12
  * @property {Array.<string>} fields Fields for stacking. The minimum is 2 fields.
13
13
  * @property {Array.<ColumnStackPlugin~StackDefinition>} stacks List of stacking configuration
14
14
  * @property {boolean=} autoStacking=false If enabled, columns will be auto stacked when new inserted column field match in stack
15
+ * @property {Function=} clicked=null Event handler when user clicks on stack/expanding icon
15
16
  */
16
17
 
17
18
  /** @typedef {Object} ColumnStackPlugin~ColumnOptions
@@ -45,6 +46,18 @@ import { preventDefault } from "../../tr-grid-util/es6/EventDispatcher.js";
45
46
  * @property {string=} activeColumn="" Column index or field for set as active column
46
47
  */
47
48
 
49
+ /** @event ColumnStackPlugin#clicked
50
+ * @description Fired when user clicks on stack/expanding icon
51
+ * @type {Object}
52
+ * @property {number} colIndex
53
+ * @property {number} rowIndex
54
+ * @property {Array.<Object>} menuData Data for populating context menu
55
+ * @property {number} activeIndex
56
+ * @property {Array.<number>} columnIndices
57
+ * @property {number} activeColIndex
58
+ * @property {Event} event Native event argument from click event
59
+ */
60
+
48
61
  /** @constructor
49
62
  * @extends {GridPlugin}
50
63
  */
@@ -55,12 +68,12 @@ var ColumnStackPlugin = function () {
55
68
  this._onColumnAdded = this._onColumnAdded.bind(this);
56
69
  this._onStackButtonClicked = this._onStackButtonClicked.bind(this);
57
70
  this._updateUI = this._updateUI.bind(this);
58
- this._setStack = this._setStack.bind(this);
71
+ this._requestStackingByFields = this._requestStackingByFields.bind(this);
59
72
  this._hosts = [];
60
73
  this._stacks = {};
61
74
 
62
75
  this._conflator = new Conflator(100, this._updateUI);
63
- this._stackConflator = new Conflator(100, this._setStack);
76
+ this._stackConflator = new Conflator(100, this._requestStackingByFields);
64
77
  };
65
78
 
66
79
  Ext.inherits(ColumnStackPlugin, GridPlugin);
@@ -73,10 +86,11 @@ ColumnStackPlugin.prototype._stacks;
73
86
  * @private
74
87
  */
75
88
  ColumnStackPlugin.prototype._pendingStacks;
76
- /** @type {Object}
89
+ /** A map from stack id to array of fields
90
+ * @type {Object}
77
91
  * @private
78
92
  */
79
- ColumnStackPlugin.prototype._columnStack = null;
93
+ ColumnStackPlugin.prototype._idToFields = null; // For auto-stacking
80
94
  /** @type {boolean}
81
95
  * @private
82
96
  */
@@ -85,6 +99,10 @@ ColumnStackPlugin.prototype._updating = false;
85
99
  * @private
86
100
  */
87
101
  ColumnStackPlugin.prototype._autoStacking = false;
102
+ /** @type {boolean}
103
+ * @private
104
+ */
105
+ ColumnStackPlugin.prototype._stacking = false;
88
106
 
89
107
 
90
108
  /** @type {number}
@@ -213,79 +231,99 @@ ColumnStackPlugin.prototype.config = function (options) {
213
231
  columns = [];
214
232
  }
215
233
 
216
- var i, len = columns.length;
217
- for(i = 0; i < len; ++i) {
218
- this._setColumnStacking(i, {}); // used for further column index getting
234
+ var i;
235
+ var colCount = columns.length;
236
+ for(i = 0; i < colCount; ++i) {
237
+ this._setUniqueRef(i, {}); // used for further column index getting
219
238
  }
220
239
 
221
- var sid, stacks = {};
222
240
  var columnStack = options.columnStack;
223
- if(columnStack != null) {
241
+ var stackId = "";
242
+ var stacks = {};
243
+ var hasStack = false;
244
+ var stackConfig = null;
245
+ if(columnStack) {
246
+ this.addListener(columnStack, "clicked");
247
+
224
248
  if(columnStack.autoStacking != null) {
225
249
  this._autoStacking = columnStack.autoStacking;
226
250
  }
227
251
 
228
252
  if(columnStack.fields && columnStack.fields.length > 1) {
229
- this._columnStack = columnStack.fields;
230
- sid = this._generateStackId();
231
- stacks[sid] = {
253
+ hasStack = true;
254
+ stackId = this._generateStackId(); // TODO: Stack id may need to be hardcoded
255
+ if(!this._idToFields) {
256
+ this._idToFields = {};
257
+ }
258
+ this._idToFields[stackId] = columnStack.fields;
259
+ stacks[stackId] = {
232
260
  colRefs: columnStack.fields,
233
261
  spreading: columnStack.spreading === true,
234
262
  collapsed: columnStack.collapsed !== false
235
263
  };
236
264
  } else if (columnStack.stacks && columnStack.stacks.length) {
265
+ hasStack = true;
237
266
  var stackLen = columnStack.stacks.length;
238
267
  for(i = 0; i < stackLen; i++){
239
- var stackConfig = columnStack.stacks[i];
240
- sid = stackConfig.id || this._generateStackId();
268
+ stackConfig = columnStack.stacks[i];
269
+ stackId = stackConfig.id || this._generateStackId();
241
270
  if(stackConfig.collapsed == null){
242
271
  stackConfig.collapsed = true;
243
272
  }
244
273
  if(stackConfig.spreading == null){
245
274
  stackConfig.spreading = false;
246
275
  }
247
- stacks[sid] = stackConfig;
276
+ stacks[stackId] = stackConfig;
248
277
  }
249
278
  }
250
- } else {
251
- var column, stackOpt;
252
- for(i = 0; i < len; ++i) {
253
- column = columns[i];
254
- stackOpt = column["stackId"] || column["stack"];
279
+ }
280
+
281
+ if(!hasStack) {
282
+ for(i = 0; i < colCount; ++i) {
283
+ var column = columns[i];
284
+ var stackOpt = column["stackId"] || column["stack"];
285
+ if(!stackOpt) {
286
+ continue;
287
+ }
288
+
289
+ stackId = "";
290
+ var spreading = false;
291
+ var collapsed = true;
255
292
  if(typeof stackOpt === "string") {
256
- if(!stacks[stackOpt]) {
257
- stacks[stackOpt] = {
258
- colRefs: [],
259
- spreading: false
260
- };
261
- }
262
- stacks[stackOpt].colRefs.push(i);
293
+ stackId = stackOpt;
263
294
  } else if(typeof stackOpt === "object") {
264
- if(!stacks[stackOpt["id"]]) {
265
- stacks[stackOpt["id"]] = {
295
+ stackConfig = stackOpt;
296
+ stackId = stackConfig["id"] || "";
297
+ spreading = stackConfig["spreading"] === true; // WARNING: Only the first column in the stack has an effect
298
+ collapsed = stackConfig["collapsed"] !== false;
299
+ }
300
+ if(stackId) {
301
+ if(!stacks[stackId]) {
302
+ stacks[stackId] = {
266
303
  colRefs: [],
267
- spreading: stackOpt["spreading"] === true,
268
- collapsed: stackOpt["collapsed"] !== false
304
+ spreading: spreading, // Default is false (stacking mode)
305
+ collapsed: collapsed // Default is true (columns are hidden)
269
306
  };
307
+ hasStack = true;
270
308
  }
271
- stacks[stackOpt["id"]].colRefs.push(i);
309
+ stacks[stackId].colRefs.push(i);
272
310
  }
273
311
  }
274
312
  }
275
313
 
276
314
  if(this._initializedGrid) {
277
- if(Object.keys(stacks).length){
278
- this.removeAllStacks(false);
315
+ if(hasStack){
316
+ this.removeAllStacks(false); // No UI update
317
+ for(stackId in stacks) {
318
+ var config = stacks[stackId];
319
+ if(!config.colRefs){
320
+ this._transformStackConfig(config);
321
+ }
322
+ this.stackColumns(config.colRefs, stackId, config);
323
+ }
279
324
  } else {
280
325
  this.removeAllStacks();
281
326
  }
282
- for(sid in stacks) {
283
- var config = stacks[sid];
284
- if(!config.colRefs){
285
- this._transformStackConfig(config);
286
- }
287
- this.stackColumns(config.colRefs, sid, config);
288
- }
289
327
  } else {
290
328
  this._pendingStacks = this._pendingStacks || stacks;
291
329
  }
@@ -337,7 +375,7 @@ ColumnStackPlugin.prototype.getConfigObject = function (gridOptions) {
337
375
  }
338
376
 
339
377
  if (this._autoStacking) {
340
- var fields = this._columnStack[stackOption.stackId];
378
+ var fields = this._idToFields[stackOption.stackId];
341
379
  var activeColumnField = this._getField(activeColIndex);
342
380
 
343
381
  stackConfigObj.fields = fields;
@@ -361,6 +399,7 @@ ColumnStackPlugin.prototype.getConfigObject = function (gridOptions) {
361
399
  };
362
400
 
363
401
  /** @override
402
+ * @ignore
364
403
  */
365
404
  ColumnStackPlugin.prototype._afterInit = function () {
366
405
  if(this._pendingStacks) {
@@ -377,50 +416,80 @@ ColumnStackPlugin.prototype._afterInit = function () {
377
416
  // In case of lazy loading
378
417
  // DO something
379
418
  };
380
- /** @private
381
- * @param {object} stackRef
419
+ /** WARNING: This method is slow
420
+ * @private
421
+ * @param {Object} stackRef
422
+ * @param {number=} colCount
382
423
  * @return {number}
383
424
  */
384
- ColumnStackPlugin.prototype._getColumnIndex = function(stackRef) {
385
- var colCount = this.getColumnCount();
386
- var stacking, index = -1;
387
- for(var i = 0; i < colCount; i++) {
388
- stacking = this._getColumnStacking(i);
389
- if(stackRef === stacking) {
390
- index = i;
391
- break;
425
+ ColumnStackPlugin.prototype._getColumnIndex = function(stackRef, colCount) {
426
+ if(stackRef) {
427
+ if(colCount == null) {
428
+ colCount = this.getColumnCount();
429
+ }
430
+ for(var i = 0; i < colCount; i++) {
431
+ if(stackRef === this._getUniqueRef(i)) {
432
+ return i;
433
+ }
434
+ }
435
+ }
436
+ return -1;
437
+ };
438
+ /** WARNING: This method is really slow
439
+ * @private
440
+ * @param {!Array.<Object>} stackRefs
441
+ * @return {!Array.<number>}
442
+ */
443
+ ColumnStackPlugin.prototype._getColumnIndices = function(stackRefs) {
444
+ var refCount = stackRefs ? stackRefs.length : 0;
445
+ var ary = new Array(refCount);
446
+ if(refCount) {
447
+ var colCount = this.getColumnCount();
448
+ for(var i = 0; i < refCount; i++) {
449
+ ary[i] = this._getColumnIndex(stackRefs[i], colCount);
392
450
  }
393
451
  }
394
- return index;
452
+ return ary;
395
453
  };
396
454
  /** @private
397
455
  * @param {number} colIndex
398
- * @param {object} stacking
456
+ * @param {!Object} refObj
399
457
  */
400
- ColumnStackPlugin.prototype._setColumnStacking = function(colIndex, stacking) {
401
- var colData = this._newColumnData(colIndex);
402
- colData["stack"] = stacking;
458
+ ColumnStackPlugin.prototype._setUniqueRef = function(colIndex, refObj) {
459
+ this._newColumnData(colIndex)["stack"] = refObj;
403
460
  };
404
461
  /** @private
405
462
  * @param {number} colIndex
406
- * @return {*}
463
+ * @return {Object}
407
464
  */
408
- ColumnStackPlugin.prototype._getColumnStacking = function(colIndex) {
409
- return this._getColumnOption(colIndex, "stack");
465
+ ColumnStackPlugin.prototype._getUniqueRef = function(colIndex) {
466
+ return this._getColumnOption(colIndex, "stack") || null;
410
467
  };
468
+ /** @private
469
+ * @return {!Array.<Object>}
470
+ */
471
+ ColumnStackPlugin.prototype._getUniqueRefs = function() {
472
+ var colCount = this.getColumnCount();
473
+ var ary = new Array(colCount);
474
+ for(var c = 0; c < colCount; ++c) {
475
+ ary[c] = this._getUniqueRef(c);
476
+ }
477
+ return ary;
478
+ };
479
+
411
480
  /** @private
412
481
  * @param {number} colIndex
413
- * @param {object} stackOptions
482
+ * @param {Object} stackOptions
414
483
  */
415
484
  ColumnStackPlugin.prototype._setColumnStackOptions = function(colIndex, stackOptions) {
416
- var stacking = this._getColumnStacking(colIndex);
417
- if(stacking) {
418
- stacking["stackOpt"] = stackOptions;
485
+ var ref = this._getUniqueRef(colIndex);
486
+ if(ref) {
487
+ ref["stackOpt"] = stackOptions;
419
488
  }
420
489
  };
421
490
  /** @private
422
- * @param {object} stackConfig
423
- * @return {object} stack config object
491
+ * @param {Object} stackConfig
492
+ * @return {Object} stack config object
424
493
  */
425
494
  ColumnStackPlugin.prototype._transformStackConfig = function(stackConfig) {
426
495
  stackConfig.colRefs = [];
@@ -458,9 +527,9 @@ ColumnStackPlugin.prototype._transformStackConfig = function(stackConfig) {
458
527
  * @return {*}
459
528
  */
460
529
  ColumnStackPlugin.prototype._getColumnStackOptions = function(colIndex) {
461
- var stacking = this._getColumnStacking(colIndex);
462
- if(stacking){
463
- return stacking["stackOpt"] || null;
530
+ var refObj = this._getUniqueRef(colIndex);
531
+ if(refObj){
532
+ return refObj["stackOpt"] || null;
464
533
  }
465
534
  return null;
466
535
  };
@@ -468,9 +537,9 @@ ColumnStackPlugin.prototype._getColumnStackOptions = function(colIndex) {
468
537
  * @param {number} colIndex
469
538
  */
470
539
  ColumnStackPlugin.prototype._removeColumnStackOptions = function(colIndex) {
471
- var stacking = this._getColumnStacking(colIndex);
472
- if(stacking) {
473
- stacking["stackOpt"] = null;
540
+ var refObj = this._getUniqueRef(colIndex);
541
+ if(refObj) {
542
+ refObj["stackOpt"] = null;
474
543
  }
475
544
  };
476
545
  /** @private
@@ -492,28 +561,12 @@ ColumnStackPlugin.prototype._setColumnVisibility = function(colIndex, shown) {
492
561
  }
493
562
  };
494
563
  /** @private
495
- * @param {number} colIndex
496
- * @param {number} destIndex
497
- */
498
- ColumnStackPlugin.prototype._moveColumn = function(colIndex, destIndex) {
499
- if(colIndex >= 0 && destIndex >= 0 && colIndex !== destIndex) {
500
- for(var i = this._hosts.length; --i >= 0;) {
501
- this._hosts[i].moveColumn(colIndex, destIndex);
502
- }
503
- }
504
- };
505
- /** @private
506
- * @param {Array.<object>} stackRefs
564
+ * @param {Array.<Object>} stackRefs
507
565
  */
508
566
  ColumnStackPlugin.prototype._moveStackedColumns = function (stackRefs) {
509
- var len = stackRefs.length;
510
- for(var i = 1; i < len; ++i) {
511
- var fromIndex = this._getColumnIndex(stackRefs[i]);
512
- var destIndex = this._getColumnIndex(stackRefs[0]); // Active Column may be shifted due to the move
513
- if(fromIndex < destIndex){
514
- destIndex -= 1;
515
- }
516
- this._moveColumn(fromIndex, destIndex + i);
567
+ var ary = this._getColumnIndices(stackRefs);
568
+ if(ary.length > 1) {
569
+ this.reorderColumns(ary, ary[0]);
517
570
  }
518
571
  };
519
572
  /** @private
@@ -709,13 +762,7 @@ ColumnStackPlugin.prototype.getMemberIndices = function(colIndex) {
709
762
  return null;
710
763
  }
711
764
 
712
- var stackRefs = colData.stackRefs;
713
- var len = stackRefs.length;
714
- var indices = [];
715
- for(var i = 0; i < len; ++i) {
716
- indices.push(this._getColumnIndex(stackRefs[i]));
717
- }
718
- return indices;
765
+ return this._getColumnIndices(colData.stackRefs);
719
766
  };
720
767
  /** @public
721
768
  * @param {number} colIndex
@@ -943,9 +990,10 @@ ColumnStackPlugin.prototype.stackColumns = function(colRefs, stackId, options) {
943
990
 
944
991
  // Save stack fields for
945
992
  if(this._autoStacking){
946
- var columnStack = this._columnStack || {};
947
- columnStack[sid] = fields;
948
- this._columnStack = columnStack;
993
+ if(!this._idToFields) {
994
+ this._idToFields = {};
995
+ }
996
+ this._idToFields[sid] = fields;
949
997
  }
950
998
 
951
999
  var len = colRefs.length;
@@ -977,7 +1025,7 @@ ColumnStackPlugin.prototype.stackColumns = function(colRefs, stackId, options) {
977
1025
  for(i = 0; i < len; ++i) {
978
1026
  colIndex = colRefs[i];
979
1027
  this._setColumnStackOptions(colIndex, stack);
980
- stack.stackRefs[i] = this._getColumnStacking(colIndex);
1028
+ stack.stackRefs[i] = this._getUniqueRef(colIndex);
981
1029
 
982
1030
  if(colIndex == activeIndex){
983
1031
  stack.activeColumn = stack.stackRefs[i];
@@ -1085,8 +1133,8 @@ ColumnStackPlugin.prototype.unstackColumns = function(colIndices) {
1085
1133
  this._setColumnVisibility(colIndex, true);
1086
1134
  }
1087
1135
 
1088
- if(this._autoStacking) {
1089
- delete this._columnStack[sid];
1136
+ if(this._idToFields) {
1137
+ delete this._idToFields[sid]; // TODO: Clear the map whenever it no longer has a member
1090
1138
  }
1091
1139
  delete this._stacks[sid]; // Remove all reference to the stack
1092
1140
  }
@@ -1104,23 +1152,21 @@ ColumnStackPlugin.prototype.unstackColumns = function(colIndices) {
1104
1152
 
1105
1153
  return dirty;
1106
1154
  };
1107
- /** @public
1108
- * @param {boolean=} enableUpdateUI set false if you want to remove without update UI
1109
- * @return {boolean} true if at least one stacking removed
1155
+ /** @private
1156
+ * @param {string} stackId
1157
+ * @return {boolean} Returns true if there is any change
1110
1158
  */
1111
- ColumnStackPlugin.prototype.removeAllStacks = function(enableUpdateUI) {
1112
- var disableUpdateUI = enableUpdateUI === false;
1113
- var dirty = false;
1114
- for(var sid in this._stacks) {
1115
- var stack = this._stacks[sid];
1116
- dirty = true;
1117
-
1118
- var stackRefs = stack.stackRefs;
1159
+ ColumnStackPlugin.prototype._removeStack = function(stackId) {
1160
+ var stack = this._stacks[stackId];
1161
+ if(!stack) {
1162
+ return false;
1163
+ }
1119
1164
 
1120
- var len = stackRefs.length;
1121
- for(var i = 0; i < len; ++i) {
1122
- var stackRef = stackRefs[i];
1123
- var colIndex = this._getColumnIndex(stackRef);
1165
+ var colIndices = this._getColumnIndices(stack.stackRefs);
1166
+ var len = colIndices.length;
1167
+ for(var i = 0; i < len; ++i) {
1168
+ var colIndex = colIndices[i];
1169
+ if(colIndex >= 0) {
1124
1170
  if(stack.collapsed && stack.spreading) {
1125
1171
  this.collapseGroup(colIndex, false);
1126
1172
  }
@@ -1128,10 +1174,38 @@ ColumnStackPlugin.prototype.removeAllStacks = function(enableUpdateUI) {
1128
1174
  this._setColumnVisibility(colIndex, true);
1129
1175
  }
1130
1176
  }
1177
+ return true;
1178
+ };
1179
+ /** @public
1180
+ * @param {string} stackId
1181
+ * @return {boolean} Returns true if there is any change
1182
+ */
1183
+ ColumnStackPlugin.prototype.removeStack = function(stackId) {
1184
+ if(this._idToFields) {
1185
+ if(this._idToFields[stackId]) {
1186
+ delete this._idToFields[stackId];
1187
+ }
1188
+ }
1189
+ if(this._removeStack(stackId)) {
1190
+ this._updateUI();
1191
+ return true;
1192
+ }
1193
+ return false;
1194
+ };
1195
+ /** @public
1196
+ * @param {boolean=} enableUpdateUI=true Set false if you want to remove without update UI
1197
+ * @return {boolean} true if at least one stacking removed
1198
+ */
1199
+ ColumnStackPlugin.prototype.removeAllStacks = function(enableUpdateUI) {
1200
+ var dirty = false;
1201
+ for(var stackId in this._stacks) {
1202
+ dirty = true;
1203
+ this._removeStack(stackId);
1204
+ }
1131
1205
  if(dirty) {
1132
- this._columnStack = {};
1206
+ this._idToFields = null;
1133
1207
  this._stacks = {};
1134
- if(!disableUpdateUI) {
1208
+ if(enableUpdateUI !== false) {
1135
1209
  this._updateUI(); // asyncronous
1136
1210
  }
1137
1211
  }
@@ -1210,15 +1284,15 @@ ColumnStackPlugin.prototype._onColumnRemoved = function (e) {
1210
1284
  var colData = /** @type{Object} */(e.columnData);
1211
1285
  if(!colData) { return; }
1212
1286
 
1213
- var stacking = colData["stack"];
1214
- if(!stacking) { return; }
1287
+ var stackRef = colData["stack"];
1288
+ if(!stackRef) { return; }
1215
1289
 
1216
- var stackOpt = stacking["stackOpt"];
1290
+ var stackOpt = stackRef["stackOpt"];
1217
1291
  if(!stackOpt) { return; }
1218
1292
 
1219
1293
  // update members
1220
1294
  if(stackOpt.stackRefs) {
1221
- var index = stackOpt.stackRefs.indexOf(stacking);
1295
+ var index = stackOpt.stackRefs.indexOf(stackRef);
1222
1296
  if(index > -1) {
1223
1297
  stackOpt.stackRefs.splice(index, 1);
1224
1298
  if(stackOpt.stackRefs.length < 2) {
@@ -1248,6 +1322,10 @@ ColumnStackPlugin.prototype._onColumnRemoved = function (e) {
1248
1322
  * @param {Object} e
1249
1323
  */
1250
1324
  ColumnStackPlugin.prototype._onColumnMoved = function (e) {
1325
+ if(this._stacking) { // during the stacking, there is no need to recalculate stacks
1326
+ return;
1327
+ }
1328
+
1251
1329
  var toIndex = e.toColIndex;
1252
1330
  var stackOpt = this._getColumnStackOptions(toIndex);
1253
1331
 
@@ -1256,7 +1334,7 @@ ColumnStackPlugin.prototype._onColumnMoved = function (e) {
1256
1334
  return;
1257
1335
  }
1258
1336
 
1259
- var stackRef = this._getColumnStacking(toIndex);
1337
+ var stackRef = this._getUniqueRef(toIndex);
1260
1338
 
1261
1339
  var leftStackOpt = this._getColumnStackOptions(toIndex - 1);
1262
1340
  var rightStackOpt = this._getColumnStackOptions(toIndex + 1);
@@ -1265,7 +1343,7 @@ ColumnStackPlugin.prototype._onColumnMoved = function (e) {
1265
1343
  if(stackOpt) {
1266
1344
  if(stackOpt === leftStackOpt) {
1267
1345
  leftStackOpt.stackRefs.splice(leftStackOpt.stackRefs.indexOf(stackRef), 1);
1268
- leftColStackRef = this._getColumnStacking(toIndex - 1);
1346
+ leftColStackRef = this._getUniqueRef(toIndex - 1);
1269
1347
  index = leftStackOpt.stackRefs.indexOf(leftColStackRef);
1270
1348
  if(index > -1) {
1271
1349
  leftStackOpt.stackRefs.splice(index + 1, 0, stackRef);
@@ -1279,7 +1357,7 @@ ColumnStackPlugin.prototype._onColumnMoved = function (e) {
1279
1357
  return;
1280
1358
  } else if(stackOpt === rightStackOpt) {
1281
1359
  rightStackOpt.stackRefs.splice(rightStackOpt.stackRefs.indexOf(stackRef), 1);
1282
- var rightColStackRef = this._getColumnStacking(toIndex + 1);
1360
+ var rightColStackRef = this._getUniqueRef(toIndex + 1);
1283
1361
  index = rightStackOpt.stackRefs.indexOf(rightColStackRef);
1284
1362
  if(index > -1) {
1285
1363
  rightStackOpt.stackRefs.splice(index, 0, stackRef);
@@ -1342,7 +1420,7 @@ ColumnStackPlugin.prototype._onColumnMoved = function (e) {
1342
1420
  rightStackOpt = this._getColumnStackOptions(rIndex);
1343
1421
  if(leftStackOpt && leftStackOpt.spreading &&
1344
1422
  (leftStackOpt === rightStackOpt)) {
1345
- leftColStackRef = this._getColumnStacking(toIndex - 1);
1423
+ leftColStackRef = this._getUniqueRef(toIndex - 1);
1346
1424
  index = leftStackOpt.stackRefs.indexOf(leftColStackRef);
1347
1425
  if(index > -1) {
1348
1426
  leftStackOpt.stackRefs.splice(index + 1, 0, stackRef);
@@ -1366,20 +1444,21 @@ ColumnStackPlugin.prototype._onColumnMoved = function (e) {
1366
1444
  */
1367
1445
  ColumnStackPlugin.prototype._onColumnAdded = function (e) {
1368
1446
  var colIndex = e.colIndex;
1369
- this._setColumnStacking(colIndex, {});
1447
+ this._setUniqueRef(colIndex, {});
1370
1448
 
1371
- var columnStack = this._columnStack;
1372
- if (columnStack) {
1373
- this._setStack(); //asynchronous
1374
- } else {
1449
+ if (this._autoStacking) {
1450
+ if(this._idToFields) {
1451
+ this._requestStackingByFields();
1452
+ }
1453
+ } else { // TODO: This logic is too complicated
1375
1454
  // add to group
1376
1455
  var leftStackOpt = this._getColumnStackOptions(colIndex - 1);
1377
1456
  var rightStackOpt = this._getColumnStackOptions(colIndex + 1);
1378
1457
  if(leftStackOpt && (leftStackOpt === rightStackOpt)) {
1379
- var leftColStackRef = this._getColumnStacking(colIndex - 1);
1380
- var stackRef = this._getColumnStacking(colIndex);
1458
+ var leftColStackRef = this._getUniqueRef(colIndex - 1);
1459
+ var stackRef = this._getUniqueRef(colIndex);
1381
1460
  var index = leftStackOpt.stackRefs.indexOf(leftColStackRef);
1382
- if(index > -1) {
1461
+ if(index > -1) { // TODO: Reuse existing logic instead of modifying states like this
1383
1462
  leftStackOpt.stackRefs.splice(index + 1, 0, stackRef);
1384
1463
  leftStackOpt.activeColumn = leftStackOpt.stackRefs[leftStackOpt.stackRefs.length - 1];
1385
1464
  this._setColumnStackOptions(colIndex, leftStackOpt);
@@ -1414,10 +1493,9 @@ ColumnStackPlugin.prototype._onStackButtonClicked = function(e) {
1414
1493
  var activeIndex = stackRefs.indexOf(colData.activeColumn);
1415
1494
 
1416
1495
  var len = stackRefs.length;
1417
- var colIndices = new Array(len);
1496
+ var colIndices = this._getColumnIndices(stackRefs);
1418
1497
  var menuData = new Array(len);
1419
1498
  for(var i = len; --i >= 0;) {
1420
- colIndices[i] = this._getColumnIndex(stackRefs[i]);
1421
1499
  menuData[i] = {
1422
1500
  value: i,
1423
1501
  selected: i === activeIndex,
@@ -1438,12 +1516,12 @@ ColumnStackPlugin.prototype._onStackButtonClicked = function(e) {
1438
1516
  /** Remove existing stacks and apply persist stack
1439
1517
  * @private
1440
1518
  */
1441
- ColumnStackPlugin.prototype._setStack = function() {
1519
+ ColumnStackPlugin.prototype._requestStackingByFields = function() {
1442
1520
  if(this._stackConflator.conflate()) {
1443
1521
  return;
1444
1522
  }
1445
1523
 
1446
- var columnStack = this._columnStack;
1524
+ var columnStack = this._idToFields;
1447
1525
  if(columnStack){
1448
1526
  this.removeAllStacks(false);
1449
1527
  for(var sid in columnStack){
@@ -1462,19 +1540,13 @@ ColumnStackPlugin.prototype._setStack = function() {
1462
1540
  * @return {!Array.<number>} Member column indices
1463
1541
  */
1464
1542
  ColumnStackPlugin.prototype.getStackMemberIndices = function(stackId) {
1465
- var memberIndices = [];
1466
- if(stackId !== null) {
1543
+ if(stackId) {
1467
1544
  var stack = this._stacks[stackId];
1468
1545
  if(stack){
1469
- var stackRefs = stack.stackRefs;
1470
- for(var i = 0; i < stackRefs.length; ++i) {
1471
- var stackRef = stackRefs[i];
1472
- var colIndex = this._getColumnIndex(stackRef);
1473
- memberIndices.push(colIndex);
1474
- }
1546
+ return this._getColumnIndices(stack.stackRefs);
1475
1547
  }
1476
1548
  }
1477
- return memberIndices;
1549
+ return [];
1478
1550
  };
1479
1551
 
1480
1552
  /** @public
@@ -1571,7 +1643,7 @@ ColumnStackPlugin.prototype.addColumnToStack = function(colRef, stackId) {
1571
1643
 
1572
1644
  // apply stacking
1573
1645
  this._setColumnStackOptions(colRef, stack);
1574
- stack.stackRefs.push(this._getColumnStacking(colRef));
1646
+ stack.stackRefs.push(this._getUniqueRef(colRef));
1575
1647
 
1576
1648
  if(stack.spreading) {
1577
1649
  stack.activeColumn = stack.stackRefs[stack.stackRefs.length - 1];
@@ -1587,58 +1659,58 @@ ColumnStackPlugin.prototype.addColumnToStack = function(colRef, stackId) {
1587
1659
  };
1588
1660
 
1589
1661
  /** @public
1590
- * @description Remove specific column from a stack
1662
+ * @description Remove specific column from its own stack
1591
1663
  * @param {number|string} colRef column field or column index
1592
1664
  */
1593
1665
  ColumnStackPlugin.prototype.removeColumnFromStack = function(colRef) {
1594
- if(typeof colRef === "string") {
1595
- colRef = this.getColumnIndex(colRef);
1596
- if(colRef < 0) {
1597
- return;
1598
- }
1666
+ var colIndex = (typeof colRef === "string") ? this.getColumnIndex(colRef) : colRef;
1667
+ if(colIndex < 0) {
1668
+ return;
1599
1669
  }
1600
1670
 
1601
- var stackId = this.getStackId(colRef);
1671
+ var stackId = this.getStackId(colIndex);
1602
1672
  var stack = this._stacks[stackId];
1603
1673
  if(!stack) {
1604
1674
  return;
1605
1675
  }
1606
1676
 
1607
- var stackMembers = this.getStackMemberIndices(stackId);
1608
1677
  var stackRefs = stack.stackRefs;
1609
-
1610
- if(stackMembers.length < 3){
1611
- this.unstackColumns(stackMembers);
1612
- } else {
1613
- var isCollapsed = stack.spreading && stack.collapsed;
1614
-
1615
- for(var i = 0; i < stackRefs.length; ++i) {
1616
- var stackRef = stackRefs[i];
1617
- var colIndex = this._getColumnIndex(stackRef);
1618
-
1619
- if(colIndex === colRef){
1620
- if(isCollapsed) {
1621
- this._collapseMember(stackMembers[i], false);
1622
- }
1623
- stackRefs.splice(i, 1);
1624
- break;
1678
+ var memberCount = stackRefs.length;
1679
+ if(memberCount <= 2) {
1680
+ if(memberCount === 2) {
1681
+ var uniqueObj = this._getUniqueRef(colIndex);
1682
+ if(uniqueObj === stackRefs[0]) { // If the first column is removed from the stack, move it to the end of stack
1683
+ // This assumes that the column order is already in correct position
1684
+ this.moveColumnById(colIndex, this._getColumnIndex(stackRefs[1]) + 1);
1625
1685
  }
1626
1686
  }
1687
+ this.removeStack(stackId); // updateUI will be called
1688
+ return;
1689
+ }
1627
1690
 
1628
- this._removeColumnStackOptions(colRef);
1629
- this._setColumnVisibility(colRef, true);
1630
-
1631
- if(stack.spreading) {
1632
- stack.activeColumn = stackRefs[stackRefs.length - 1];
1633
- stack.collapsed = isCollapsed;
1634
- } else {
1635
- stack.activeColumn = stackRefs[0];
1691
+ var colIndices = this.getStackMemberIndices(stackId);
1692
+ var memberIdx = colIndices.indexOf(colIndex);
1693
+ var isCollapsed = stack.spreading && stack.collapsed;
1694
+ if(memberIdx >= 0) {
1695
+ if(isCollapsed) {
1696
+ this._collapseMember(colIndices[memberIdx], false); // TODO: This may change the column index
1636
1697
  }
1637
- this._stacks[stackId] = stack;
1698
+ stackRefs.splice(memberIdx, 1); // WARNING: colIndices is out of sync with stackRefs after this line
1699
+ }
1638
1700
 
1639
- this._moveStackedColumns(stack.stackRefs);
1640
- this._updateUI();
1701
+ this._removeColumnStackOptions(colIndex);
1702
+ this._setColumnVisibility(colIndex, true);
1703
+
1704
+ if(stack.spreading) {
1705
+ stack.activeColumn = stackRefs[stackRefs.length - 1];
1706
+ stack.collapsed = isCollapsed;
1707
+ } else {
1708
+ stack.activeColumn = stackRefs[0];
1641
1709
  }
1710
+ this._stacks[stackId] = stack; // TODO: This is unnecessary
1711
+
1712
+ this.moveColumnById(colIndex, colIndices[memberCount - 1] + 1); // This assumes that the column order is already in correct position
1713
+ this._updateUI();
1642
1714
  };
1643
1715
 
1644
1716
  /** @public
@@ -1742,6 +1814,64 @@ ColumnStackPlugin.prototype.getActiveColumnField = function(stackId) {
1742
1814
  return field;
1743
1815
  };
1744
1816
 
1817
+ /** @public
1818
+ * @param {string} stackId
1819
+ * @param {number|string} colRef Column field or column index
1820
+ */
1821
+ ColumnStackPlugin.prototype.addStackChild = function(stackId, colRef) {
1822
+ this.addColumnToStack(colRef, stackId);
1823
+ };
1824
+ /**
1825
+ * @public
1826
+ * @param {string} stackId
1827
+ * @param {number|string} colRef Column field or column index
1828
+ */
1829
+ ColumnStackPlugin.prototype.removeStackChild = function(stackId, colRef) {
1830
+ var colIndex = (typeof colRef === "string") ? this.getColumnIndex(colRef) : colRef;
1831
+ if(colIndex >= 0) {
1832
+ if(stackId === this.getStackId(colIndex)) {
1833
+ this.removeColumnFromStack(colIndex);
1834
+ }
1835
+ }
1836
+ };
1837
+ /** @public
1838
+ * @function
1839
+ * @param {number|string} colRef Column field or column index
1840
+ */
1841
+ ColumnStackPlugin.prototype.unsetParent = ColumnStackPlugin.prototype.removeColumnFromStack;
1842
+
1843
+ /** Move and reorder the specified columns to position before the destination
1844
+ * @public
1845
+ * @param {Array.<number|string>} colList Column list to be reordered
1846
+ * @param {(number|string)=} destCol Destination column id or index
1847
+ * @return {boolean}
1848
+ */
1849
+ ColumnStackPlugin.prototype.reorderColumns = function(colList, destCol) {
1850
+ var dirty = false;
1851
+ this._stacking = false;
1852
+
1853
+ this._reorderColumns(colList, destCol);
1854
+
1855
+ this._stacking = true;
1856
+ return dirty;
1857
+ };
1858
+ /** Move the specified column to position before the destination
1859
+ * @public
1860
+ * @param {number|string} srcCol Source column id or index
1861
+ * @param {(number|string)=} destCol Destination column id or index
1862
+ * @return {boolean}
1863
+ */
1864
+ ColumnStackPlugin.prototype.moveColumnById = function(srcCol, destCol) {
1865
+ var dirty = false;
1866
+ this._stacking = false;
1867
+
1868
+ this._moveColumnById(srcCol, destCol);
1869
+
1870
+ this._stacking = true;
1871
+ return dirty;
1872
+ };
1873
+
1874
+
1745
1875
 
1746
1876
  export default ColumnStackPlugin;
1747
1877
  export { ColumnStackPlugin, ColumnStackPlugin as ColumnStack, ColumnStackPlugin as ColumnStackExtension };