@refinitiv-ui/efx-grid 6.0.41 → 6.0.43

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 (91) hide show
  1. package/lib/column-format-dialog/lib/column-format-dialog.d.ts +1 -0
  2. package/lib/column-format-dialog/lib/column-format-dialog.js +3 -24
  3. package/lib/column-format-dialog/lib/preview-table.d.ts +1 -1
  4. package/lib/column-format-dialog/lib/preview-table.js +15 -27
  5. package/lib/core/dist/core.js +843 -871
  6. package/lib/core/dist/core.min.js +1 -1
  7. package/lib/core/es6/grid/Core.d.ts +4 -0
  8. package/lib/core/es6/grid/Core.js +67 -2
  9. package/lib/core/es6/grid/plugins/SortableTitlePlugin.d.ts +3 -2
  10. package/lib/core/es6/grid/plugins/SortableTitlePlugin.js +32 -26
  11. package/lib/core/es6/grid/util/util.js +25 -9
  12. package/lib/formatters/es6/CoralButtonFormatter.d.ts +2 -2
  13. package/lib/formatters/es6/CoralCheckboxFormatter.d.ts +1 -1
  14. package/lib/formatters/es6/CoralComboBoxFormatter.d.ts +4 -4
  15. package/lib/formatters/es6/CoralIconFormatter.d.ts +3 -3
  16. package/lib/formatters/es6/CoralInputFormatter.d.ts +1 -1
  17. package/lib/formatters/es6/CoralRadioButtonFormatter.d.ts +2 -2
  18. package/lib/formatters/es6/CoralSelectFormatter.d.ts +4 -4
  19. package/lib/formatters/es6/CoralToggleFormatter.d.ts +1 -1
  20. package/lib/formatters/es6/DuplexEmeraldDateTimePickerFormatter.d.ts +1 -1
  21. package/lib/formatters/es6/EFButtonFormatter.d.ts +2 -2
  22. package/lib/formatters/es6/EFCheckboxFormatter.d.ts +1 -1
  23. package/lib/formatters/es6/EFComboBoxFormatter.d.ts +4 -4
  24. package/lib/formatters/es6/EFDateTimePickerFormatter.d.ts +1 -1
  25. package/lib/formatters/es6/EFIconFormatter.d.ts +3 -3
  26. package/lib/formatters/es6/EFNumberFieldFormatter.d.ts +1 -1
  27. package/lib/formatters/es6/EFRadioButtonFormatter.d.ts +2 -2
  28. package/lib/formatters/es6/EFSelectFormatter.d.ts +4 -4
  29. package/lib/formatters/es6/EFTextFieldFormatter.d.ts +1 -1
  30. package/lib/formatters/es6/EFToggleFormatter.d.ts +1 -1
  31. package/lib/formatters/es6/EmeraldDateTimePickerFormatter.d.ts +1 -1
  32. package/lib/formatters/es6/FormatterBuilder.d.ts +6 -2
  33. package/lib/formatters/es6/FormatterBuilder.js +328 -178
  34. package/lib/formatters/es6/NumericInputFormatter.d.ts +1 -1
  35. package/lib/formatters/es6/PercentBarFormatter.d.ts +6 -6
  36. package/lib/formatters/es6/SimpleImageFormatter.d.ts +3 -3
  37. package/lib/formatters/es6/SimpleInputFormatter.d.ts +1 -1
  38. package/lib/formatters/es6/SimpleLinkFormatter.d.ts +3 -3
  39. package/lib/formatters/es6/SimpleTickerFormatter.d.ts +3 -3
  40. package/lib/formatters/es6/SimpleToggleFormatter.d.ts +3 -3
  41. package/lib/formatters/es6/TextFormatter.d.ts +1 -1
  42. package/lib/grid/index.js +1 -1
  43. package/lib/rt-grid/dist/rt-grid.js +213 -44
  44. package/lib/rt-grid/dist/rt-grid.min.js +1 -1
  45. package/lib/rt-grid/es6/Grid.d.ts +24 -1
  46. package/lib/rt-grid/es6/Grid.js +92 -4
  47. package/lib/tr-grid-column-grouping/es6/ColumnGrouping.d.ts +4 -0
  48. package/lib/tr-grid-column-grouping/es6/ColumnGrouping.js +34 -19
  49. package/lib/tr-grid-column-stack/es6/ColumnStack.d.ts +9 -3
  50. package/lib/tr-grid-column-stack/es6/ColumnStack.js +324 -388
  51. package/lib/tr-grid-filter-input/es6/FilterInput.d.ts +17 -17
  52. package/lib/tr-grid-filter-input/es6/FilterInput.js +146 -33
  53. package/lib/tr-grid-util/es6/DateTime.js +3 -3
  54. package/lib/tr-grid-util/es6/GridPlugin.js +1 -1
  55. package/lib/types/es6/ColumnGrouping.d.ts +4 -0
  56. package/lib/types/es6/ColumnStack.d.ts +9 -3
  57. package/lib/types/es6/CoralButtonFormatter.d.ts +2 -2
  58. package/lib/types/es6/CoralCheckboxFormatter.d.ts +1 -1
  59. package/lib/types/es6/CoralComboBoxFormatter.d.ts +4 -4
  60. package/lib/types/es6/CoralIconFormatter.d.ts +3 -3
  61. package/lib/types/es6/CoralInputFormatter.d.ts +1 -1
  62. package/lib/types/es6/CoralRadioButtonFormatter.d.ts +2 -2
  63. package/lib/types/es6/CoralSelectFormatter.d.ts +4 -4
  64. package/lib/types/es6/CoralToggleFormatter.d.ts +1 -1
  65. package/lib/types/es6/Core/grid/Core.d.ts +4 -0
  66. package/lib/types/es6/Core/grid/plugins/SortableTitlePlugin.d.ts +3 -2
  67. package/lib/types/es6/DuplexEmeraldDateTimePickerFormatter.d.ts +1 -1
  68. package/lib/types/es6/EFButtonFormatter.d.ts +2 -2
  69. package/lib/types/es6/EFCheckboxFormatter.d.ts +1 -1
  70. package/lib/types/es6/EFComboBoxFormatter.d.ts +4 -4
  71. package/lib/types/es6/EFDateTimePickerFormatter.d.ts +1 -1
  72. package/lib/types/es6/EFIconFormatter.d.ts +3 -3
  73. package/lib/types/es6/EFNumberFieldFormatter.d.ts +1 -1
  74. package/lib/types/es6/EFRadioButtonFormatter.d.ts +2 -2
  75. package/lib/types/es6/EFSelectFormatter.d.ts +4 -4
  76. package/lib/types/es6/EFTextFieldFormatter.d.ts +1 -1
  77. package/lib/types/es6/EFToggleFormatter.d.ts +1 -1
  78. package/lib/types/es6/EmeraldDateTimePickerFormatter.d.ts +1 -1
  79. package/lib/types/es6/FilterInput.d.ts +17 -17
  80. package/lib/types/es6/FormatterBuilder.d.ts +6 -2
  81. package/lib/types/es6/NumericInputFormatter.d.ts +1 -1
  82. package/lib/types/es6/PercentBarFormatter.d.ts +6 -6
  83. package/lib/types/es6/RealtimeGrid/Grid.d.ts +22 -0
  84. package/lib/types/es6/SimpleImageFormatter.d.ts +3 -3
  85. package/lib/types/es6/SimpleInputFormatter.d.ts +1 -1
  86. package/lib/types/es6/SimpleLinkFormatter.d.ts +3 -3
  87. package/lib/types/es6/SimpleTickerFormatter.d.ts +3 -3
  88. package/lib/types/es6/SimpleToggleFormatter.d.ts +3 -3
  89. package/lib/types/es6/TextFormatter.d.ts +1 -1
  90. package/lib/versions.json +6 -6
  91. package/package.json +1 -1
@@ -12,7 +12,7 @@ import { preventDefault } from "../../tr-grid-util/es6/EventDispatcher.js";
12
12
  * @description Available options describing `columnStack` object specified in grid's option
13
13
  * @property {Array.<string>} fields Fields for stacking. The minimum is 2 fields.
14
14
  * @property {Array.<ColumnStackPlugin~StackDefinition>} stacks List of stacking configuration
15
- * @property {boolean=} autoStacking=false If enabled, columns will be auto stacked when new inserted column field match in stack
15
+ * @property {boolean=} autoStacking Deprecated. Stacks are automatically maintained as long as its members exist
16
16
  * @property {Function=} clicked=null Event handler when user clicks on stack/expanding icon
17
17
  */
18
18
 
@@ -31,13 +31,13 @@ import { preventDefault } from "../../tr-grid-util/es6/EventDispatcher.js";
31
31
 
32
32
  /** @typedef {Object} ColumnStackPlugin~StackDefinition
33
33
  * @description Available options for setting stack
34
- * @property {string} id Group ID
34
+ * @property {string} id Group Id
35
35
  * @property {boolean=} spreading=false If specified true, this group will be running in collapsing mode
36
36
  * @property {boolean=} collapsed=true If disabled, this group will be expanded at the first time
37
- * @property {Array.<string>} children Children column ID. Used when autoStacking is disabled
38
- * @property {Array.<string>} fields Children fiields. Used when autoStacking is enabled
37
+ * @property {Array.<string>=} children=null List of column Ids for the stack members. String in this array is assumed to be column ids
38
+ * @property {Array.<string>=} fields=null List of column fields for the stack members. This will override children property
39
39
  * @property {string=} name="" Name defined for specific stack
40
- * @property {string=} activeColumn="" If enable autoStacking, field of active column in stack. Else, column Id of active column in stack.
40
+ * @property {string=} activeColumn="" Column Id or field of the active column.
41
41
  */
42
42
 
43
43
  /** @typedef {Object} ColumnStackPlugin~StackConfiguration
@@ -50,41 +50,48 @@ import { preventDefault } from "../../tr-grid-util/es6/EventDispatcher.js";
50
50
  /** @event ColumnStackPlugin#clicked
51
51
  * @description Fired when user clicks on stack/expanding icon
52
52
  * @type {Object}
53
- * @property {number} colIndex
54
- * @property {number} rowIndex
53
+ * @property {number} colIndex The column index that was clicked
54
+ * @property {number} rowIndex The row index that was clicked
55
55
  * @property {Array.<Object>} menuData Data for populating context menu
56
- * @property {number} activeIndex
57
- * @property {Array.<number>} columnIndices
58
- * @property {number} activeColIndex
56
+ * @property {number} activeIndex The index of the item in the menuData that corresponds to the active column
57
+ * @property {Array.<number>} columnIndices Members column index
58
+ * @property {number} activeColIndex The column index that is currently active
59
59
  * @property {Event} event Native event argument from click event
60
+ * @property {boolean} spreading True if the column being clicked is a member of the collapsing group
61
+ * @property {boolean} collapsed True If the clicked group is collapsed
60
62
  */
61
63
 
62
64
  /** @private
63
65
  * @function
64
- * @param {Array} refA
65
- * @param {Array} refB
66
+ * @param {Object} indexMap
67
+ * @param {*} refA
68
+ * @param {*} refB
66
69
  * @return {number}
67
70
  */
68
- var compareRef = function(refA, refB) {
69
- var valA = refA[0];
70
- var valB = refB[0];
71
- var invalidA = (valA == null || valA < 0);
72
- var invalidB = (valB == null || valB < 0);
73
-
74
- if(invalidA) {
75
- return invalidB ? 0 : 1;
76
- } else if(invalidB) {
77
- return -1;
78
- }
79
- if(valA < valB) {
80
- return -1;
71
+ var _indexSorter = function(indexMap, refA, refB) {
72
+ var numA = indexMap[refA];
73
+ var numB = indexMap[refB];
74
+ if(numA === numB) {
75
+ return 0;
81
76
  }
82
- if(valB < valA) {
77
+ if(numA < 0) {
83
78
  return 1;
84
79
  }
85
-
86
- return 0;
80
+ if(numB < 0) {
81
+ return -1;
82
+ }
83
+ return numA - numB;
87
84
  };
85
+ /** @private
86
+ * @function
87
+ * @param {Object} indexMap
88
+ * @param {*} refA
89
+ * @return {boolean}
90
+ */
91
+ var _byValidIndex = function(indexMap, refA) {
92
+ return indexMap[refA] >= 0;
93
+ };
94
+
88
95
  /** @private
89
96
  * @description Resolve active column from the given stack object, if activeColumn is invalid
90
97
  * @param {Object} stackOpt
@@ -95,7 +102,6 @@ var _resolveActiveColumn = function(stackOpt) {
95
102
  var children = stackOpt.children;
96
103
  if(children && children.length) {
97
104
  var activeColumn = stackOpt.activeColumn;
98
- // TODO: If columns are stored as column id and activeColumn is a field, active index could not be found
99
105
  if(!activeColumn || children.indexOf(activeColumn) < 0) {
100
106
  stackOpt.activeColumn = stackOpt.spreading ? children[children.length - 1] : children[0];
101
107
  return true;
@@ -119,14 +125,12 @@ var ColumnStackPlugin = function () {
119
125
 
120
126
  this._onStackButtonClicked = this._onStackButtonClicked.bind(this);
121
127
  this._updateUI = this._updateUI.bind(this);
122
- this._requestStackingByFields = this._requestStackingByFields.bind(this);
123
- this._toIdOrField = this._toIdOrField.bind(this);
128
+ this._toColumnId = this._toColumnId.bind(this);
124
129
 
125
130
  this._hosts = [];
126
131
  this._groupDefs = new GroupDefinitions();
127
132
 
128
133
  this._conflator = new Conflator(50, this._updateUI);
129
- this._stackConflator = new Conflator(100, this._requestStackingByFields);
130
134
  };
131
135
 
132
136
  Ext.inherits(ColumnStackPlugin, GridPlugin);
@@ -139,23 +143,20 @@ ColumnStackPlugin.prototype._groupDefs;
139
143
  * @private
140
144
  */
141
145
  ColumnStackPlugin.prototype._pendingStacks;
142
- /** A map from stack id to array of fields
143
- * @type {Object}
146
+ /** @type {Object.<string, string>}
144
147
  * @private
145
148
  */
146
- ColumnStackPlugin.prototype._idToFields = null; // For auto-stacking
149
+ ColumnStackPlugin.prototype._usingField = false;
150
+
147
151
  /** @type {boolean}
148
152
  * @private
149
153
  */
150
154
  ColumnStackPlugin.prototype._updating = false;
151
- /** @type {boolean}
152
- * @private
153
- */
154
- ColumnStackPlugin.prototype._autoStacking = false;
155
- /** @type {boolean}
155
+
156
+ /** @type {number}
156
157
  * @private
157
158
  */
158
- ColumnStackPlugin.prototype._inReordering = false;
159
+ ColumnStackPlugin.prototype._inReordering = 0;
159
160
  /** @type {boolean}
160
161
  * @private
161
162
  */
@@ -243,7 +244,6 @@ ColumnStackPlugin.prototype.unload = function (host) {
243
244
 
244
245
  if(this._hosts.length <= 0) {
245
246
  this._conflator.reset();
246
- this._stackConflator.reset();
247
247
  this._groupDefs.removeAllGroups();
248
248
  }
249
249
  this._dispose();
@@ -261,10 +261,14 @@ ColumnStackPlugin._styles = prettifyCss([
261
261
  "margin: 0;",
262
262
  "justify-content: center;"
263
263
  ],
264
- ".tr-grid .collapsed .cell.grouping .front-panel, " +
265
- ".tr-grid .collapsed .cell.grouping .floating-panel *:not(.stack-icon)", [
264
+ ".tr-grid .collapsed .cell.grouping .front-panel," +
265
+ ".tr-grid .collapsed .cell.grouping .floating-panel *:not(.stack-icon)," +
266
+ ".tr-grid .collapsed .cell.grouping .sort-symbol", [ // V3 Hide arrow sorting in collapse state in speading mode
266
267
  "display: none;"
267
268
  ],
269
+ ".floating-panel .stack-icon", [
270
+ "cursor: pointer;" // change the mouse cursor on the collapsed stack icon to allow for expansion but disallow sorting
271
+ ],
268
272
  ".tr-grid .collapsed .cell.grouping .floating-panel .stack-icon", [
269
273
  "margin-left: 0;"
270
274
  ],
@@ -307,23 +311,18 @@ ColumnStackPlugin.prototype.config = function (options) {
307
311
  var stackConfig = null;
308
312
  if(columnStack) {
309
313
  this.addListener(columnStack, "clicked");
310
-
311
- if(columnStack.autoStacking != null) {
312
- this._autoStacking = columnStack.autoStacking;
313
- }
314
+ this._usingField = false;
314
315
 
315
316
  if(columnStack.fields && columnStack.fields.length > 1) {
317
+ this._usingField = true;
318
+
316
319
  hasStack = true;
317
320
  stackId = this._generateStackId(); // TODO: Stack id may need to be hardcoded
318
- if(!this._idToFields) {
319
- this._idToFields = {};
320
- }
321
- this._idToFields[stackId] = columnStack.fields;
322
321
  stacks[stackId] = {
323
322
  id: stackId,
324
323
  spreading: columnStack.spreading === true,
325
324
  collapsed: columnStack.collapsed !== false,
326
- children: columnStack.fields
325
+ fields: columnStack.fields
327
326
  };
328
327
  } else if (columnStack.stacks && columnStack.stacks.length) {
329
328
  hasStack = true;
@@ -331,7 +330,7 @@ ColumnStackPlugin.prototype.config = function (options) {
331
330
  for(i = 0; i < stackLen; i++){
332
331
  stackConfig = columnStack.stacks[i];
333
332
  stackId = stackConfig.id || this._generateStackId();
334
- if(stackConfig.collapsed == null){
333
+ if(stackConfig.collapsed == null){ // TODO: consolidate with the above
335
334
  stackConfig.collapsed = true;
336
335
  }
337
336
  if(stackConfig.spreading == null){
@@ -365,7 +364,7 @@ ColumnStackPlugin.prototype.config = function (options) {
365
364
  }
366
365
  if(stackId) {
367
366
  stackOpt = stacks[stackId];
368
- if(!stackOpt ) {
367
+ if(!stackOpt) {
369
368
  stackOpt = stacks[stackId] = {
370
369
  id: stackId,
371
370
  spreading: spreading, // Default is false (stacking mode)
@@ -399,50 +398,13 @@ ColumnStackPlugin.prototype.config = function (options) {
399
398
  ColumnStackPlugin.prototype.getConfigObject = function (gridOptions) {
400
399
  var obj = gridOptions || {};
401
400
 
402
- var stacks = this._groupDefs.getGroupMap();
403
- var stackOptions = [];
404
-
405
- for (var stackKey in stacks) {
406
- var stackOption = stacks[stackKey];
407
- var activeColIndex = this.getColumnIndex(stackOption.activeColumn);
401
+ // TODO: Handle the case where pendingStacks has not been applied
402
+ var stackOptions = this.getStacks();
408
403
 
409
- var stackConfigObj = {
410
- id: stackOption.id
411
- };
412
- var name = stackOption.name;
413
- var collapsed = stackOption.collapsed;
414
- var spreading = stackOption.spreading;
415
-
416
- if (name) {
417
- stackConfigObj.name = name;
418
- }
419
- if (collapsed !== true) {
420
- stackConfigObj.collapsed = collapsed;
421
- }
422
- if (spreading !== false) {
423
- stackConfigObj.spreading = spreading;
424
- }
425
-
426
- if (this._autoStacking) {
427
- var fields = this._idToFields[stackOption.id];
428
- var activeColumnField = this._getField(activeColIndex);
429
-
430
- stackConfigObj.fields = fields;
431
- stackConfigObj.activeColumn = activeColumnField;
432
-
433
- } else {
434
- stackConfigObj.children = this.getStackMemberIds(stackOption.id);
435
- if(stackOption.activeColumn) {
436
- stackConfigObj.activeColumn = stackOption.activeColumn; // WARNING: Column Id or field
437
- }
438
- }
439
- stackOptions.push(stackConfigObj);
404
+ if(stackOptions.length) {
405
+ obj.columnStack = {};
406
+ obj.columnStack.stacks = stackOptions;
440
407
  }
441
-
442
- obj.columnStack = {};
443
- obj.columnStack.stacks = stackOptions;
444
- obj.columnStack.autoStacking = this._autoStacking;
445
-
446
408
  return obj;
447
409
  };
448
410
 
@@ -460,44 +422,18 @@ ColumnStackPlugin.prototype._afterInit = function () {
460
422
 
461
423
  /** @private
462
424
  * @param {*} colRef
463
- * @return {string} column id or field
425
+ * @return {string} column id
464
426
  */
465
- ColumnStackPlugin.prototype._toIdOrField = function(colRef) {
427
+ ColumnStackPlugin.prototype._toColumnId = function(colRef) {
466
428
  if(typeof colRef !== "string") {
467
429
  if(typeof colRef === "number") {
468
430
  return this.getColumnId(colRef);
469
- // return this._getField(colRef);
470
431
  }
471
432
  return "";
472
433
  }
473
434
  return colRef || "";
474
435
  };
475
436
  /** @private
476
- * @param {Object} stackConfig
477
- */
478
- ColumnStackPlugin.prototype._transformStackConfig = function(stackConfig) {
479
- var children = stackConfig.children;
480
- var childCount = children ? children.length : 0;
481
- if(childCount) { // Fields or ids
482
- for(var i = 0; i < childCount; i++){
483
- var childRef = this._toIdOrField(children[i]);
484
- if(childRef) {
485
- children[i] = childRef;
486
- }
487
- }
488
- } else if(stackConfig.fields) {
489
- stackConfig.children = stackConfig.fields;
490
- } else if(!stackConfig.children) {
491
- stackConfig.children = [];
492
- }
493
- if(!this._autoStacking) { // TODO: This may not be necessary
494
- var activeColumn = this._toIdOrField(stackConfig.activeColumn);
495
- if(activeColumn) {
496
- stackConfig.activeColumn = activeColumn;
497
- }
498
- }
499
- };
500
- /** @private
501
437
  * @param {Object=} stacks
502
438
  */
503
439
  ColumnStackPlugin.prototype._applyUserConfigs = function(stacks) {
@@ -505,8 +441,13 @@ ColumnStackPlugin.prototype._applyUserConfigs = function(stacks) {
505
441
  this.removeAllStacks(false); // No UI update
506
442
  for(var stackId in stacks) {
507
443
  var stack = stacks[stackId];
508
- this._transformStackConfig(stack);
509
- this.stackColumns(stack.children, stackId, stack);
444
+ var children = stack.children;
445
+ var fields = stack.fields;
446
+ if(fields) { // Convert all fields and indices to column Ids
447
+ this._usingField = true;
448
+ children = fields; // override children with fields
449
+ }
450
+ this.stackColumns(children, stackId, stack);
510
451
  }
511
452
  } else {
512
453
  this.removeAllStacks(); // with UI update
@@ -518,19 +459,9 @@ ColumnStackPlugin.prototype._applyUserConfigs = function(stacks) {
518
459
  * @return {Object}
519
460
  */
520
461
  ColumnStackPlugin.prototype._getColumnStackOptions = function(colIndex) {
521
- var colCount = this.getColumnCount();
522
- if(colIndex >= 0 && colIndex < colCount) {
462
+ if(colIndex >= 0 && colIndex < this.getColumnCount()) {
523
463
  var colId = this.getColumnId(colIndex);
524
- var stack = this._groupDefs.getParentGroup(colId);
525
- if(stack) {
526
- return stack;
527
- }
528
-
529
- var field = this._getField(colIndex);
530
- stack = this._groupDefs.getParentGroup(field);
531
- if(stack) {
532
- return stack;
533
- }
464
+ return this._groupDefs.getParentGroup(colId) || null;
534
465
  }
535
466
  return null;
536
467
  };
@@ -590,13 +521,6 @@ ColumnStackPlugin.prototype._moveStackedColumns = function (colRefs) {
590
521
  }
591
522
  };
592
523
  /** @private
593
- * @return {number}
594
- */
595
- ColumnStackPlugin.prototype._getColumnCount = function() {
596
- var host = this._host || this._hosts[0];
597
- return host ? host.getColumnCount() : 0;
598
- };
599
- /** @private
600
524
  * @return {boolean}
601
525
  */
602
526
  ColumnStackPlugin.prototype._isIconAvailable = function() {
@@ -681,7 +605,7 @@ ColumnStackPlugin.prototype._updateUI = function() {
681
605
  }
682
606
 
683
607
  this._updating = true;
684
- var colCount = this._getColumnCount();
608
+ var colCount = this.getColumnCount();
685
609
  var gridCount = this._hosts.length;
686
610
  var stackOpt, spreading;
687
611
  for(var c = 0; c < colCount; ++c) {
@@ -957,7 +881,7 @@ ColumnStackPlugin.prototype.isColumnActive = function(colIndex) {
957
881
  };
958
882
 
959
883
  /** @public
960
- * @param {number|string} colRef Column index, id, or field
884
+ * @param {number|string} colRef Column Id, index or field
961
885
  * @return {string}
962
886
  */
963
887
  ColumnStackPlugin.prototype.getStackId = function(colRef) {
@@ -971,16 +895,12 @@ ColumnStackPlugin.prototype.getStackId = function(colRef) {
971
895
  return "";
972
896
  };
973
897
  /** @public
974
- * @param {Array.<number|string>=} colRefs Names of fields or column indices. If not specified, selected columns will be used.
898
+ * @param {Array.<number|string>=} colRefs Column Ids, indices, or fields. If not specified, selected columns will be used.
975
899
  * @param {string=} stackId Must be unique
976
900
  * @param {ColumnStackPlugin~StackConfiguration=} options
977
901
  * @return {boolean} Return true if there is any change.
978
902
  */
979
903
  ColumnStackPlugin.prototype.stackColumns = function(colRefs, stackId, options) {
980
- if(!options) {
981
- options = {};
982
- }
983
-
984
904
  var updateRequired = false;
985
905
  var sid = stackId;
986
906
  if(sid) {
@@ -1004,10 +924,14 @@ ColumnStackPlugin.prototype.stackColumns = function(colRefs, stackId, options) {
1004
924
  return updateRequired; // Only two or more columns can be stacked
1005
925
  }
1006
926
 
927
+ if(!options) {
928
+ options = {};
929
+ }
1007
930
  // Clone user data
1008
931
  var isSpreading = options.spreading === true;
1009
932
  var isCollapsed = options.collapsed !== false;
1010
933
  var activeColumn = options.activeColumn || ""; // field or id
934
+ // WARNING: fields property in user option is ignored
1011
935
  var stack = {};
1012
936
  stack.id = sid;
1013
937
  stack.name = options.name || "";
@@ -1015,7 +939,7 @@ ColumnStackPlugin.prototype.stackColumns = function(colRefs, stackId, options) {
1015
939
  stack.collapsed = isCollapsed;
1016
940
  stack.activeColumn = activeColumn; // field or id
1017
941
 
1018
- // If grid is not initialize, add setting to pending stacks
942
+ // If grid is not initialized, add setting to pending stacks
1019
943
  if(!this._initializedGrid) {
1020
944
  var pendingStacks = this._pendingStacks;
1021
945
  if(!pendingStacks) {
@@ -1026,17 +950,7 @@ ColumnStackPlugin.prototype.stackColumns = function(colRefs, stackId, options) {
1026
950
  return false;
1027
951
  }
1028
952
 
1029
- var children = colRefs.map(this._toIdOrField);
1030
953
  var colIndices = this.getColumnIndices(colRefs); // WARNING: Invalid columns are filtered out
1031
- var validCount = colIndices.length;
1032
-
1033
- // Save stack fields for autoStacking
1034
- if(this._autoStacking){
1035
- if(!this._idToFields) {
1036
- this._idToFields = {};
1037
- }
1038
- this._idToFields[sid] = children;
1039
- }
1040
954
 
1041
955
  // Prevent columns already in a stack from moving out to another stack
1042
956
  if(!this.isColumnStackable(colIndices)) {
@@ -1046,17 +960,14 @@ ColumnStackPlugin.prototype.stackColumns = function(colRefs, stackId, options) {
1046
960
  return updateRequired;
1047
961
  }
1048
962
 
1049
- // TODO: If columns are stored as column id and activeColumn is a field, active index could not be found
1050
- stack.children = children;
963
+ // WARNING: Invalid columns are filtered out
964
+ var children = colIndices.map(this._toColumnId); // All fields and indices from colRefs will be converted to column Ids
965
+ stack.children = children; // Note: children property now contains only valid column ids
966
+
1051
967
  var activeIndex = -1;
1052
968
  if(activeColumn && typeof activeColumn === "string") {
1053
969
  activeIndex = this.getColumnIndex(activeColumn);
1054
- if(children.indexOf(activeColumn) < 0) { // children and activeColumn may have different type
1055
- var field = this._getField(activeIndex);
1056
- if(field === activeColumn) {
1057
- stack.activeColumn = activeColumn = this.getColumnId(activeIndex);
1058
- }
1059
- }
970
+ stack.activeColumn = activeColumn = this.getColumnId(activeIndex); // Convert field or invalid column id to a valid id
1060
971
  } else if(typeof activeColumn === "number"){
1061
972
  activeIndex = activeColumn;
1062
973
  }
@@ -1072,6 +983,7 @@ ColumnStackPlugin.prototype.stackColumns = function(colRefs, stackId, options) {
1072
983
  this.reorderColumns(colIndices, colIndices[0]);
1073
984
 
1074
985
  // Update column selection
986
+ var validCount = colIndices.length;
1075
987
  if(!isSpreading) {
1076
988
  var csp = this._getPlugin("ColumnSelectionPlugin");
1077
989
  if(csp && csp.isEnabled()){
@@ -1160,11 +1072,8 @@ ColumnStackPlugin.prototype._freezeColumn = function(frozenColIndex, numRightCol
1160
1072
 
1161
1073
  /** @public
1162
1074
  * @description Replace all of the stacking in the Grid with a new one.
1163
- * Grid stores the stacked fields indefinitely.
1164
- * When adding columns, Grid will attempt to restore stacking,
1165
- * if there are at least two visible columns that match to the retained fields.
1166
- * @param {Array.<number|string>=} colRefs Field names or column indices
1167
- * @param {number|string=} activeColRef Field names or column index of active column
1075
+ * @param {Array.<number|string>=} colRefs Column Ids, indices, or fields.
1076
+ * @param {(number|string)=} activeColRef Column Id, index, or field.
1168
1077
  * @return {boolean} If the stack has been updated, return true.
1169
1078
  */
1170
1079
  ColumnStackPlugin.prototype.setStack = function(colRefs, activeColRef) {
@@ -1180,35 +1089,88 @@ ColumnStackPlugin.prototype.setStack = function(colRefs, activeColRef) {
1180
1089
  return true;
1181
1090
  };
1182
1091
  /** @public
1183
- * @param {Array.<number>=} colIndices Selected columns will be used, if it is not given
1184
- * @return {boolean}
1092
+ * @description Remove all existing stacks and apply the given stack definitions to the Grid
1093
+ * @param {Array.<ColumnStackPlugin~StackDefinition>} stacks Array of stack definition objects
1185
1094
  */
1186
- ColumnStackPlugin.prototype.unstackColumns = function(colIndices) {
1187
- if(!colIndices) {
1188
- colIndices = this._getSelectedColumns();
1095
+ ColumnStackPlugin.prototype.setStacks = function(stacks) {
1096
+ this.removeAllStacks();
1097
+
1098
+ var stackCount = stacks ? stacks.length : 0;
1099
+ for(var i = 0; i < stackCount; ++i) {
1100
+ var stack = stacks[i];
1101
+ if(stack) {
1102
+ if(stack.children) {
1103
+ this.stackColumns(stack.children, stack.id, stack);
1104
+ }
1105
+ }
1189
1106
  }
1107
+ };
1108
+ /** @public
1109
+ * @description Get stack defintion objects like those returned from getConfigObject
1110
+ * @return {!Array.<ColumnStackPlugin~StackDefinition>} Array of stack definition objects
1111
+ */
1112
+ ColumnStackPlugin.prototype.getStacks = function() {
1113
+ var stacks = this._groupDefs.getGroupMap();
1114
+ var stackOptions = [];
1190
1115
 
1191
- var i, colIndex;
1192
- var len = colIndices.length;
1193
- var stacks = {};
1194
- var colCount = this.getColumnCount();
1116
+ for (var stackKey in stacks) {
1117
+ var stackOption = stacks[stackKey];
1118
+ var stackId = stackOption.id;
1195
1119
 
1196
- for(i = 0; i < len; ++i) {
1197
- colIndex = colIndices[i];
1198
- if(colIndex < colCount) {
1199
- var stackOpt = this._getColumnStackOptions(colIndex);
1200
- if(stackOpt) {
1201
- stacks[stackOpt.id] = 1; // Exclude duplicate stacks
1120
+ var stackConfigObj = {
1121
+ id: stackId
1122
+ };
1123
+ var name = stackOption.name;
1124
+ var collapsed = stackOption.collapsed;
1125
+ var spreading = stackOption.spreading;
1126
+
1127
+ if (name) {
1128
+ stackConfigObj.name = name;
1129
+ }
1130
+ if (collapsed !== true) {
1131
+ stackConfigObj.collapsed = collapsed;
1132
+ }
1133
+ if (spreading !== false) {
1134
+ stackConfigObj.spreading = spreading;
1135
+ }
1136
+
1137
+ if (this._usingField) {
1138
+ var colIndices = this.getStackMemberIndices(stackId);
1139
+ var memberCount = colIndices.length;
1140
+ var fields = new Array(memberCount);
1141
+ for(var i = 0; i < memberCount; ++i) {
1142
+ fields[i] = this.getColumnField(colIndices[i]);
1143
+ }
1144
+ stackConfigObj.fields = fields;
1145
+ stackConfigObj.activeColumn = this.getActiveColumnField(stackId);
1146
+ } else {
1147
+ stackConfigObj.children = this.getStackMemberIds(stackId).slice();
1148
+ if(stackOption.activeColumn) {
1149
+ stackConfigObj.activeColumn = stackOption.activeColumn;
1202
1150
  }
1203
1151
  }
1152
+ stackOptions.push(stackConfigObj);
1153
+ }
1154
+ return stackOptions;
1155
+ };
1156
+
1157
+ /** @public
1158
+ * @param {Array.<number>=} colIndices Selected columns will be used, if it is not given
1159
+ * @return {boolean}
1160
+ */
1161
+ ColumnStackPlugin.prototype.unstackColumns = function(colIndices) {
1162
+ if(!colIndices) {
1163
+ colIndices = this._getSelectedColumns();
1204
1164
  }
1205
1165
 
1206
1166
  var dirty = false;
1207
- for(var sid in stacks) {
1208
- dirty = true;
1209
- this._removeStack(sid);
1210
- if(this._idToFields) {
1211
- delete this._idToFields[sid]; // TODO: Clear the map whenever it no longer has a member
1167
+ var len = colIndices.length;
1168
+ for(var i = 0; i < len; ++i) {
1169
+ var colIndex = colIndices[i];
1170
+ var stackOpt = this._getColumnStackOptions(colIndex);
1171
+ if(stackOpt) {
1172
+ dirty = true;
1173
+ this._removeStack(stackOpt.id);
1212
1174
  }
1213
1175
  }
1214
1176
  if(dirty) {
@@ -1249,11 +1211,6 @@ ColumnStackPlugin.prototype._removeStack = function(stackId) {
1249
1211
  * @return {boolean} Returns true if there is any change
1250
1212
  */
1251
1213
  ColumnStackPlugin.prototype.removeStack = function(stackId) {
1252
- if(this._idToFields) {
1253
- if(this._idToFields[stackId]) {
1254
- delete this._idToFields[stackId];
1255
- }
1256
- }
1257
1214
  if(this._removeStack(stackId)) {
1258
1215
  this._updateUI();
1259
1216
  return true;
@@ -1267,11 +1224,10 @@ ColumnStackPlugin.prototype.removeStack = function(stackId) {
1267
1224
  ColumnStackPlugin.prototype.removeAllStacks = function(enableUpdateUI) {
1268
1225
  var groupIds = this._groupDefs.getGroupIds();
1269
1226
  var groupCount = groupIds.length;
1270
- for(var i = 0; i < groupCount; ++i) {
1271
- this._removeStack(groupIds[i]);
1272
- }
1273
1227
  if(groupCount) {
1274
- this._idToFields = null;
1228
+ for(var i = 0; i < groupCount; ++i) {
1229
+ this._removeStack(groupIds[i]);
1230
+ }
1275
1231
  this._groupDefs.removeAllGroups(); // TODO: May not necessary
1276
1232
 
1277
1233
  if(enableUpdateUI !== false) {
@@ -1297,16 +1253,11 @@ ColumnStackPlugin.prototype.setActiveColumn = function(activeColumn) {
1297
1253
 
1298
1254
  var colId = this.getColumnId(colIndex);
1299
1255
  var stack = this._groupDefs.getParentGroup(colId);
1300
- var field = "";
1301
- if(!stack) {
1302
- field = this._getField(colIndex);
1303
- stack = this._groupDefs.getParentGroup(field);
1304
- }
1305
1256
  if(!stack) {
1306
1257
  return false;
1307
1258
  }
1308
1259
  var chdr = stack.children;
1309
- var memberIndex = field ? chdr.indexOf(field) : chdr.indexOf(colId);
1260
+ var memberIndex = chdr.indexOf(colId);
1310
1261
  if(memberIndex < 0) {
1311
1262
  return false;
1312
1263
  }
@@ -1387,21 +1338,11 @@ ColumnStackPlugin.prototype._onColumnRemoved = function (e) {
1387
1338
  return;
1388
1339
  }
1389
1340
 
1390
- var colRef = "";
1391
1341
  var colId = e.colId;
1392
1342
  var stackOpt = this._groupDefs.getParentGroup(colId);
1393
1343
 
1394
- if(stackOpt) {
1395
- colRef = colId;
1396
- } else {
1397
- var colData = /** @type{Object} */(e.columnData);
1398
- var field = colData ? colData.field : "";
1399
- stackOpt = this._groupDefs.getParentGroup(field);
1400
- if(stackOpt) {
1401
- colRef = field;
1402
- } else {
1403
- return;
1404
- }
1344
+ if(!stackOpt) {
1345
+ return;
1405
1346
  }
1406
1347
  // update members
1407
1348
  var children = stackOpt.children;
@@ -1409,7 +1350,7 @@ ColumnStackPlugin.prototype._onColumnRemoved = function (e) {
1409
1350
  this._removeStack(stackOpt.id);
1410
1351
  this._updateUI();
1411
1352
  } else {
1412
- this._groupDefs.removeGroupChild(stackOpt.id, colRef);
1353
+ this._groupDefs.removeGroupChild(stackOpt.id, colId);
1413
1354
  this._updateActiveColumn(stackOpt); // This may trigger _updateUI
1414
1355
  }
1415
1356
  };
@@ -1418,21 +1359,17 @@ ColumnStackPlugin.prototype._onColumnRemoved = function (e) {
1418
1359
  */
1419
1360
  ColumnStackPlugin.prototype._onColumnMoved = function (e) {
1420
1361
  if(this._inReordering || this._inResetting) {
1362
+ if(this._inReordering) {
1363
+ this._inReordering = 2; // Mark dirty
1364
+ }
1421
1365
  return; // during the reordering or resetting, there is no need to recalculate stacks
1422
1366
  }
1423
1367
 
1424
1368
  var toIndex = e.toColIndex;
1425
- var colRef = "";
1426
1369
  var colId = this.getColumnId(toIndex);
1427
1370
  var stackOpt = this._groupDefs.getParentGroup(colId);
1428
- if(stackOpt) {
1429
- colRef = colId;
1430
- } else {
1431
- var field = this._getField(toIndex);
1432
- stackOpt = this._groupDefs.getParentGroup(field);
1433
- if(stackOpt) {
1434
- colRef = field;
1435
- }
1371
+ if(!stackOpt) {
1372
+ return;
1436
1373
  }
1437
1374
 
1438
1375
  var leftStackOpt = this._getColumnStackOptions(toIndex - 1);
@@ -1449,7 +1386,7 @@ ColumnStackPlugin.prototype._onColumnMoved = function (e) {
1449
1386
  if(stackOpt.children.length <= 2) {
1450
1387
  this._removeStack(stackOpt.id);
1451
1388
  } else {
1452
- this._removeRefFromStack(stackOpt, colRef, toIndex);
1389
+ this._removeRefFromStack(stackOpt, colId, toIndex);
1453
1390
  }
1454
1391
  }
1455
1392
  dirty = true;
@@ -1471,18 +1408,15 @@ ColumnStackPlugin.prototype._onColumnMoved = function (e) {
1471
1408
  * @param {Object} e
1472
1409
  */
1473
1410
  ColumnStackPlugin.prototype._onColumnAdded = function (e) {
1474
- var colIndex = e.colIndex;
1411
+ if(this._inResetting) {
1412
+ return;
1413
+ }
1475
1414
 
1476
- if (this._autoStacking) {
1477
- if(this._idToFields) {
1478
- this._requestStackingByFields();
1479
- }
1480
- } else if(!this._inResetting) {
1481
- var stackOpt = this._isWithinStack(colIndex);
1482
- if(stackOpt) {
1483
- if(this._addRefToStack(stackOpt, colIndex)) {
1484
- this._updateUI();
1485
- }
1415
+ var colIndex = e.colIndex;
1416
+ var stackOpt = this._isWithinStack(colIndex);
1417
+ if(stackOpt) {
1418
+ if(this._addRefToStack(stackOpt, colIndex)) {
1419
+ this._updateUI();
1486
1420
  }
1487
1421
  }
1488
1422
  };
@@ -1493,26 +1427,38 @@ ColumnStackPlugin.prototype._onBeforeBatchOperation = function (e) {
1493
1427
  if(e.batchType === "reset") {
1494
1428
  this._inResetting = true;
1495
1429
  } else if(e.batchType === "move") {
1496
- this._inReordering = true;
1430
+ this._inReordering = 1;
1497
1431
  }
1498
1432
  };
1499
1433
  /** @private
1500
1434
  * @param {Object} e
1501
1435
  */
1502
1436
  ColumnStackPlugin.prototype._onAfterBatchOperation = function (e) {
1437
+ var groups, groupCount, i, group;
1503
1438
  if(e.batchType === "reset") {
1504
1439
  this._inResetting = false;
1505
- // TODO: Revalidate members in stacks
1506
- // TODO: Reposition members and stacks
1507
- var groups = this._groupDefs.getGroups();
1508
- var groupCount = groups.length;
1509
- for(var i = 0; i < groupCount; ++i) {
1510
- var group = groups[i];
1440
+
1441
+ groups = this._groupDefs.getGroups();
1442
+ groupCount = groups.length;
1443
+ for(i = 0; i < groupCount; ++i) {
1444
+ this._repositionMembers(groups[i], true); // validate the group
1445
+ }
1446
+ groups = this._groupDefs.getGroups();
1447
+ groupCount = groups.length;
1448
+ for(i = 0; i < groupCount; ++i) {
1449
+ group = groups[i];
1511
1450
  this._updateActiveColumn(group);
1512
1451
  this._hideStackedColumns(group);
1513
1452
  }
1514
1453
  } else if(e.batchType === "move") {
1515
- this._inReordering = false;
1454
+ if(this._inReordering === 2) {
1455
+ groups = this._groupDefs.getGroups();
1456
+ groupCount = groups.length;
1457
+ for(i = 0; i < groupCount; ++i) {
1458
+ this._repositionMembers(groups[i]);
1459
+ }
1460
+ }
1461
+ this._inReordering = 0;
1516
1462
  }
1517
1463
  };
1518
1464
  /** @private
@@ -1547,12 +1493,12 @@ ColumnStackPlugin.prototype._isWithinStack = function (colIndex) {
1547
1493
  * @return {boolean}
1548
1494
  */
1549
1495
  ColumnStackPlugin.prototype._addRefToStack = function (stackOption, colIndex) {
1550
- var colId = this._toIdOrField(colIndex);
1496
+ var colId = this._toColumnId(colIndex);
1551
1497
 
1552
1498
  this._hideStackedColumns(stackOption, colIndex);
1553
1499
 
1554
1500
  // Find a position to be placed in the stack
1555
- var rightColRef = this._toIdOrField(colIndex + 1);
1501
+ var rightColRef = this._toColumnId(colIndex + 1);
1556
1502
  var children = stackOption.children;
1557
1503
  var pos = children.indexOf(rightColRef); // WARNING This does not work for field
1558
1504
  return this._groupDefs.addGroupChild(stackOption.id, colId, pos);
@@ -1582,23 +1528,50 @@ ColumnStackPlugin.prototype._removeRefFromStack = function (stackOption, colRef,
1582
1528
 
1583
1529
  /** @private
1584
1530
  * @param {Object} stackOption
1531
+ * @param {boolean=} validate Remove invalid members and stack
1585
1532
  */
1586
- ColumnStackPlugin.prototype._repositionMembers = function (stackOption) {
1533
+ ColumnStackPlugin.prototype._repositionMembers = function (stackOption, validate) {
1587
1534
  var children = stackOption.children;
1588
1535
  var refCount = children ? children.length : 0;
1589
- if(!refCount) {
1590
- return;
1591
- }
1592
1536
 
1593
- var i;
1594
- var indexToIds = new Array(refCount);
1595
- for(i = 0; i < refCount; i++) {
1537
+ var indexMap = {};
1538
+ var prevIndex = -1;
1539
+ var dirty = false;
1540
+ var hasInvalid = false;
1541
+ for(var i = 0; i < refCount; i++) {
1596
1542
  var colRef = children[i];
1597
- indexToIds[i] = [this.getColumnIndex(colRef), colRef];
1543
+ var colIndex = this.getColumnIndex(colRef);
1544
+ indexMap[colRef] = colIndex;
1545
+ if(colIndex >= 0) {
1546
+ if(colIndex < prevIndex) {
1547
+ dirty = true;
1548
+ }
1549
+ } else { // Found invalid member
1550
+ hasInvalid = true;
1551
+ }
1552
+ prevIndex = colIndex;
1598
1553
  }
1599
- indexToIds.sort(compareRef);
1600
- for(i = 0; i < refCount; i++) {
1601
- children[i] = indexToIds[i][1];
1554
+ if(validate && hasInvalid) {
1555
+ children = children.filter(_byValidIndex.bind(null, indexMap));
1556
+ // WARNING: this._groupDefs._childToParent may be out of sync after children are filtered
1557
+ // TODO: Create a new API to rebuild childToParent map
1558
+ this._groupDefs.removeAllChildren(stackOption.id);
1559
+ stackOption.children = children;
1560
+ this._groupDefs.setGroup(stackOption.id, stackOption);
1561
+
1562
+ refCount = children.length;
1563
+ }
1564
+
1565
+ if(refCount < 2) {
1566
+ if(validate) {
1567
+ this._removeStack(stackOption.id);
1568
+ this._updateUI();
1569
+ }
1570
+ return;
1571
+ }
1572
+
1573
+ if(dirty || hasInvalid) {
1574
+ children.sort(_indexSorter.bind(null, indexMap));
1602
1575
  }
1603
1576
  };
1604
1577
  /** @private
@@ -1618,27 +1591,31 @@ ColumnStackPlugin.prototype._onStackButtonClicked = function(e) {
1618
1591
 
1619
1592
  e.stopPropagation();
1620
1593
 
1621
- if(colData.spreading) {
1622
- this.collapseGroup(colIndex, !colData.collapsed);
1623
- return;
1624
- }
1625
-
1626
1594
  var children = colData.children;
1627
- var activeIndex = children.indexOf(colData.activeColumn);
1628
-
1629
- var len = children.length;
1630
1595
  var colIndices = this.getColumnIndices(children);
1631
- var menuData = new Array(len);
1632
- for(var i = len; --i >= 0;) {
1633
- menuData[i] = {
1634
- value: i,
1635
- selected: i === activeIndex,
1636
- label: this.getColumnName(colIndices[i]),
1637
- field: this._getField(colIndices[i])
1638
- };
1596
+ if(colData.spreading) {
1597
+ var collapsed = !colData.collapsed;
1598
+ this.collapseGroup(colIndex, collapsed);
1599
+ pos["menuData"] = null;
1600
+ pos["activeIndex"] = -1;
1601
+ pos["collapsed"] = collapsed;
1602
+ } else {
1603
+ var activeIndex = children.indexOf(colData.activeColumn);
1604
+ var len = children.length;
1605
+ var menuData = new Array(len);
1606
+ for(var i = len; --i >= 0;) {
1607
+ menuData[i] = {
1608
+ value: i,
1609
+ selected: i === activeIndex,
1610
+ label: this.getColumnName(colIndices[i]),
1611
+ field: this.getColumnField(colIndices[i])
1612
+ };
1613
+ }
1614
+ pos["menuData"] = menuData;
1615
+ pos["activeIndex"] = activeIndex;
1616
+ pos["collapsed"] = false;
1639
1617
  }
1640
- pos["menuData"] = menuData;
1641
- pos["activeIndex"] = activeIndex;
1618
+ pos["spreading"] = colData.spreading;
1642
1619
  pos["columnIndices"] = colIndices;
1643
1620
  pos["activeColIndex"] = this.getColumnIndex(colData.activeColumn);
1644
1621
  pos["event"] = e;
@@ -1648,40 +1625,13 @@ ColumnStackPlugin.prototype._onStackButtonClicked = function(e) {
1648
1625
  this._dispatch("clicked", pos);
1649
1626
  };
1650
1627
 
1651
- /** Remove existing stacks and apply persist stack
1652
- * @private
1653
- */
1654
- ColumnStackPlugin.prototype._requestStackingByFields = function() {
1655
- if(this._stackConflator.conflate()) {
1656
- return;
1657
- }
1658
-
1659
- var columnStack = this._idToFields;
1660
- if(columnStack){
1661
- this.removeAllStacks(false);
1662
- for(var sid in columnStack){
1663
- var fields = columnStack[sid];
1664
- var colIndices = this.getColumnIndices(fields);
1665
- if (colIndices.length > 1) {
1666
- this.stackColumns(fields, sid);
1667
- }
1668
- }
1669
- }
1670
- };
1671
-
1672
1628
  /** @public
1673
1629
  * @description Get member column indices in a stack
1674
1630
  * @param {string} stackId
1675
1631
  * @return {!Array.<number>} Member column indices
1676
1632
  */
1677
1633
  ColumnStackPlugin.prototype.getStackMemberIndices = function(stackId) {
1678
- if(stackId) {
1679
- var stack = this._groupDefs.getGroup(stackId);
1680
- if(stack){
1681
- return this.getColumnIndices(stack.children);
1682
- }
1683
- }
1684
- return [];
1634
+ return this.getColumnIndices(this.getStackMemberIds(stackId));
1685
1635
  };
1686
1636
 
1687
1637
  /** @public
@@ -1689,13 +1639,14 @@ ColumnStackPlugin.prototype.getStackMemberIndices = function(stackId) {
1689
1639
  * @param {string} stackId
1690
1640
  * @return {!Array.<string>} Member column ids
1691
1641
  */
1692
- ColumnStackPlugin.prototype.getStackMemberIds = function(stackId) {
1693
- var colIndices = this.getStackMemberIndices(stackId);
1694
- if(colIndices.length) {
1695
- return colIndices.map(this._toIdOrField);
1642
+ ColumnStackPlugin.prototype.getStackMemberIds = function(stackId) { // WARNING: This does not filter out invalid members
1643
+ if(stackId) {
1644
+ var stack = this._groupDefs.getGroup(stackId);
1645
+ if(stack){
1646
+ return stack.children;
1647
+ }
1696
1648
  }
1697
-
1698
- return colIndices;
1649
+ return [];
1699
1650
  };
1700
1651
 
1701
1652
  /** @public
@@ -1740,13 +1691,25 @@ ColumnStackPlugin.prototype.getColumnIndicesByColumnIds = function(colIds) {
1740
1691
  * @return {!Array.<string>} Column indices
1741
1692
  */
1742
1693
  ColumnStackPlugin.prototype.getColumnIdsByFields = function(fields) {
1743
- if(!Array.isArray(fields)){
1744
- fields = [fields];
1694
+ if(!fields) {
1695
+ return [];
1696
+ }
1697
+ var ary = Array.isArray(fields) ? fields : [fields];
1698
+ var count = fields.length;
1699
+ var outAry = new Array(count);
1700
+ for(var i = 0; i < count; ++i) {
1701
+ var ref = ary[i];
1702
+ var colIndex = -1;
1703
+ if(typeof ref === "number") {
1704
+ colIndex = ref;
1705
+ } else if(ref) {
1706
+ if(typeof ref === "string") {
1707
+ colIndex = this.getColumnIndex(ref);
1708
+ }
1709
+ }
1710
+ outAry[i] = (colIndex >= 0) ? this.getColumnId(colIndex) : "";
1745
1711
  }
1746
-
1747
- var colIndices = this.getColumnIndices(fields);
1748
-
1749
- return this.getColumnIdsByIndex(colIndices);
1712
+ return outAry;
1750
1713
  };
1751
1714
 
1752
1715
  /** @public
@@ -1755,7 +1718,7 @@ ColumnStackPlugin.prototype.getColumnIdsByFields = function(fields) {
1755
1718
  * @param {string} stackId
1756
1719
  */
1757
1720
  ColumnStackPlugin.prototype.addColumnToStack = function(colRef, stackId) {
1758
- var colId = this._toIdOrField(colRef);
1721
+ var colId = this._toColumnId(colRef);
1759
1722
 
1760
1723
  var stack = this._groupDefs.getGroup(stackId);
1761
1724
  var isColumnStackable = !this._groupDefs.getParentGroup(colId);
@@ -1805,15 +1768,6 @@ ColumnStackPlugin.prototype.removeColumnFromStack = function(colRef) {
1805
1768
 
1806
1769
  var colId = this.getColumnId(colIndex);
1807
1770
  var stack = this._groupDefs.getParentGroup(colId);
1808
- if(stack) {
1809
- colRef = colId;
1810
- } else {
1811
- var field = this._getField(colIndex);
1812
- stack = this._groupDefs.getParentGroup(field);
1813
- if(stack) {
1814
- colRef = field;
1815
- }
1816
- }
1817
1771
 
1818
1772
  if(!stack) {
1819
1773
  return;
@@ -1823,7 +1777,7 @@ ColumnStackPlugin.prototype.removeColumnFromStack = function(colRef) {
1823
1777
  var memberCount = children.length;
1824
1778
  if(memberCount <= 2) {
1825
1779
  if(memberCount === 2) {
1826
- if(colRef === children[0]) { // If the first column is removed from the stack, move it to the end of stack
1780
+ if(colId === children[0]) { // If the first column is removed from the stack, move it to the end of stack
1827
1781
  // This assumes that the column order is already in correct position
1828
1782
  this.moveColumnById(colIndex, this.getColumnIndex(children[1]) + 1);
1829
1783
  }
@@ -1842,7 +1796,7 @@ ColumnStackPlugin.prototype.removeColumnFromStack = function(colRef) {
1842
1796
 
1843
1797
  /** @public
1844
1798
  * @description Reorder columns in a stack
1845
- * @param {Array.<number|string>} colRefs column fields or column indices
1799
+ * @param {Array.<number|string>} colRefs Column Ids, indices, or fields
1846
1800
  * @param {string} stackId
1847
1801
  */
1848
1802
  ColumnStackPlugin.prototype.reorderStackColumns = function(colRefs, stackId) {
@@ -1850,47 +1804,24 @@ ColumnStackPlugin.prototype.reorderStackColumns = function(colRefs, stackId) {
1850
1804
  if(!stack) {
1851
1805
  return;
1852
1806
  }
1853
-
1854
- var stackMemberIndices = this.getStackMemberIndices(stackId);
1855
- var stackMemberCount = stackMemberIndices.length;
1856
- var len = colRefs.length;
1857
- if(len) {
1858
- if(typeof colRefs[0] === "string") {
1859
- colRefs = this.getColumnIndices(colRefs);
1860
- }
1807
+ if(!colRefs || !colRefs.length) {
1808
+ return; // Nothing to be reordered
1861
1809
  }
1862
-
1863
- var newStackMembers = [];
1864
- var i, colIndex;
1865
- for(i = 0; i < len; i++ ){
1866
- colIndex = colRefs[i];
1867
- if(stackMemberIndices.indexOf(colIndex) >= 0){
1868
- newStackMembers.push(colIndex);
1869
- }
1810
+ var colIndices = this.getColumnIndices(colRefs); // Slow
1811
+ if(!colIndices.length) {
1812
+ return; // Given input has no valid column
1870
1813
  }
1871
- if(newStackMembers.length !== stackMemberCount){
1872
- for(i = 0; i < stackMemberCount; i++ ){
1873
- colIndex = stackMemberIndices[i];
1874
- if(newStackMembers.indexOf(colIndex) < 0){
1875
- newStackMembers.push(colIndex);
1876
- if(newStackMembers.length === stackMemberCount){
1877
- break;
1878
- }
1879
- }
1880
- }
1881
- }
1882
-
1883
- var options = {
1884
- spreading: stack.spreading,
1885
- collapsed: stack.collapsed
1886
- };
1887
1814
 
1888
- for(i = 0; i < newStackMembers.length; i++){
1889
- newStackMembers[i] = this._getField(newStackMembers[i]);
1815
+ var curMemberIndices = this.getStackMemberIndices(stackId); // Slow
1816
+ var memberCount = curMemberIndices.length;
1817
+ var indexMap = {};
1818
+ for(var i = 0; i < memberCount; ++i) {
1819
+ var colIndex = curMemberIndices[i];
1820
+ indexMap[colIndex] = colIndices.indexOf(colIndex);
1890
1821
  }
1891
1822
 
1892
- this.removeStack(stackId);
1893
- this.stackColumns(newStackMembers, stackId, options);
1823
+ curMemberIndices.sort(_indexSorter.bind(null, indexMap));
1824
+ this.reorderColumns(curMemberIndices, curMemberIndices[0]);
1894
1825
  };
1895
1826
 
1896
1827
  /** @public
@@ -1911,13 +1842,25 @@ ColumnStackPlugin.prototype.getStackName = function(stackId) {
1911
1842
  return this._groupDefs.getGroupName(stackId);
1912
1843
  };
1913
1844
 
1845
+ /** @public
1846
+ * @description Get active column id of specific stack
1847
+ * @param {string} stackId
1848
+ * @return {string} active column id
1849
+ */
1850
+ ColumnStackPlugin.prototype.getActiveColumnId = function(stackId) {
1851
+ var stack = this._groupDefs.getGroup(stackId);
1852
+ if(stack){
1853
+ return stack.activeColumn || "";
1854
+ }
1855
+ return "";
1856
+ };
1914
1857
  /** @public
1915
1858
  * @description Get active column field of specific stack
1916
1859
  * @param {string} stackId
1917
1860
  * @return {string} active column field
1918
1861
  */
1919
1862
  ColumnStackPlugin.prototype.getActiveColumnField = function(stackId) {
1920
- return this._getField(this.getActiveColumnIndex(stackId));
1863
+ return this.getColumnField(this.getActiveColumnIndex(stackId));
1921
1864
  };
1922
1865
 
1923
1866
  /** @public
@@ -1932,11 +1875,10 @@ ColumnStackPlugin.prototype.getActiveColumnIndex = function(stackId) {
1932
1875
  }
1933
1876
  return -1;
1934
1877
  };
1935
- //getActiveColumnIndex
1936
1878
 
1937
1879
  /** @public
1938
1880
  * @param {string} stackId
1939
- * @param {number|string} colRef Column field or column index
1881
+ * @param {number|string} colRef Column Id, index or field
1940
1882
  */
1941
1883
  ColumnStackPlugin.prototype.addStackChild = function(stackId, colRef) {
1942
1884
  this.addColumnToStack(colRef, stackId);
@@ -1944,7 +1886,7 @@ ColumnStackPlugin.prototype.addStackChild = function(stackId, colRef) {
1944
1886
  /**
1945
1887
  * @public
1946
1888
  * @param {string} stackId
1947
- * @param {number|string} colRef Column field or column index
1889
+ * @param {number|string} colRef Column Id, index or field
1948
1890
  */
1949
1891
  ColumnStackPlugin.prototype.removeStackChild = function(stackId, colRef) {
1950
1892
  if(stackId === this.getStackId(colRef)) {
@@ -1953,7 +1895,7 @@ ColumnStackPlugin.prototype.removeStackChild = function(stackId, colRef) {
1953
1895
  };
1954
1896
  /** @public
1955
1897
  * @function
1956
- * @param {number|string} colRef Column field or column index
1898
+ * @param {number|string} colRef Column Id, index or field
1957
1899
  */
1958
1900
  ColumnStackPlugin.prototype.unsetParent = ColumnStackPlugin.prototype.removeColumnFromStack;
1959
1901
 
@@ -1964,13 +1906,7 @@ ColumnStackPlugin.prototype.unsetParent = ColumnStackPlugin.prototype.removeColu
1964
1906
  * @return {boolean}
1965
1907
  */
1966
1908
  ColumnStackPlugin.prototype.reorderColumns = function(colList, destCol) {
1967
- var dirty = false;
1968
- this._inReordering = true;
1969
-
1970
- dirty = this._reorderColumns(colList, destCol);
1971
-
1972
- this._inReordering = false;
1973
- return dirty;
1909
+ return this._reorderColumns(colList, destCol);
1974
1910
  };
1975
1911
  /** Move the specified column to position before the destination
1976
1912
  * @public
@@ -2070,7 +2006,7 @@ ColumnStackPlugin.prototype.moveStack = function(stackId, destCol) {
2070
2006
  if(!stackId){
2071
2007
  return false;
2072
2008
  }
2073
- var colList = this.getStackMemberIds(stackId); // WARNING: column ids or fields
2009
+ var colList = this.getStackMemberIds(stackId);
2074
2010
  var dirty = this.reorderColumns(colList, destCol);
2075
2011
  return dirty;
2076
2012
  };
@@ -2093,7 +2029,7 @@ ColumnStackPlugin.prototype.pinStack = function(stackId, side) {
2093
2029
  var leftPinnedIndex = host.getFrozenColumnCount() - 1;
2094
2030
  var rightPinnedCount = host.getPinnedRightColumnCount();
2095
2031
  var colCount = this.getColumnCount();
2096
- var colList = this.getStackMemberIds(stackId); // WARNING: column ids or fields
2032
+ var colList = this.getStackMemberIds(stackId);
2097
2033
  var len = colList.length;
2098
2034
 
2099
2035
  var dest;
@@ -2148,7 +2084,7 @@ ColumnStackPlugin.prototype.unpinStack = function(stackId, dest) {
2148
2084
  var rightPinnedCount = host.getPinnedRightColumnCount();
2149
2085
  var colCount = this.getColumnCount();
2150
2086
  var firstRightPinnedIndex = colCount - rightPinnedCount;
2151
- var colList = this.getStackMemberIds(stackId); // WARNING: column ids or fields
2087
+ var colList = this.getStackMemberIds(stackId);
2152
2088
  var len = colList.length;
2153
2089
 
2154
2090
  var destId = null;