@refinitiv-ui/efx-grid 6.0.126 → 6.0.127

Sign up to get free protection for your applications and to get access to all the features.
@@ -8621,8 +8621,7 @@ EventDispatcher_EventDispatcher._proto = EventDispatcher_EventDispatcher.prototy
8621
8621
 
8622
8622
 
8623
8623
 
8624
- /**
8625
- * Trigger when data within the table has been changed
8624
+ /** @description Trigger when data within the table has been changed
8626
8625
  * @event DataCache#dataChanged
8627
8626
  * @property {boolean} globalChange Indicates a big change. User should expect all data has been change
8628
8627
  * @property {string} type Type of changes. Possible values are "inserted", "removed", "updated", and undefined
@@ -8630,32 +8629,34 @@ EventDispatcher_EventDispatcher._proto = EventDispatcher_EventDispatcher.prototy
8630
8629
  * @property {Object.<string, *>} rowData Column values of the changed row in JSON object format
8631
8630
  */
8632
8631
 
8633
- /**
8634
- * Trigger before DataCache#dataChanged. Perform any data update during the event will NOT cause more dataChanged events
8632
+ /** @description Trigger before DataCache#dataChanged. Perform any data update during the event will NOT cause more dataChanged events
8635
8633
  * @event DataCache#dataComposed
8636
8634
  */
8637
8635
 
8638
- /**
8636
+ /** Class for caching data and firing event when data is changed
8639
8637
  * @constructor
8640
8638
  * @extends {EventDispatcher}
8641
8639
  */
8642
8640
  let DataCache = function () {
8643
- let _t = this;
8644
-
8645
- _t._rows = {};
8646
- _t._subs = {};
8647
- _t._onInsert = _t._onInsert.bind(_t);
8648
- _t._onUpdate = _t._onUpdate.bind(_t);
8649
- _t._onDelete = _t._onDelete.bind(_t);
8650
- _t._onQ2DataChanged = _t._onQ2DataChanged.bind(_t);
8651
- _t._onQ2SubAdded = _t._onQ2SubAdded.bind(_t);
8652
- _t._onQ2SubRemoved = _t._onQ2SubRemoved.bind(_t);
8641
+ this._rows = {};
8653
8642
 
8654
- _t._addEvent("dataComposed");
8655
- _t._addEvent("dataChanged");
8643
+ this._addEvent("dataComposed");
8644
+ this._addEvent("dataChanged");
8656
8645
  };
8657
8646
  es6_Ext.inherits(DataCache, event_EventDispatcher);
8658
8647
 
8648
+ /** @protected
8649
+ * @ignore
8650
+ * @type {!Object.<string, Object>}
8651
+ */
8652
+ DataCache.prototype._rows;
8653
+
8654
+ /** @protected
8655
+ * @ignore
8656
+ * @type {boolean}
8657
+ */
8658
+ DataCache.prototype._composing = false;
8659
+
8659
8660
  //#region Public
8660
8661
  /**
8661
8662
  * @public
@@ -8663,162 +8664,64 @@ es6_Ext.inherits(DataCache, event_EventDispatcher);
8663
8664
  DataCache.prototype.dispose = function () {
8664
8665
  this.unlistenAll();
8665
8666
  this.clearAllData(true);
8666
- this._quotes2 = null;
8667
8667
  };
8668
8668
 
8669
- /**
8670
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility. This API supports only Quotes2's "Subscriptions" object.
8669
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8671
8670
  * @public
8672
- * @param {Object} subs Subscriptions object from JET.Quotes2
8671
+ * @ignore
8673
8672
  */
8674
- DataCache.prototype.setSubscriptions = function (subs) {
8675
- if (this._quotes2) {
8676
- this._quotes2["removeEventListener"]("dataChanged", this._onQ2DataChanged);
8677
- this._quotes2["removeEventListener"]("subscriptionAdded", this._onQ2SubAdded);
8678
- this._quotes2["removeEventListener"]("subscriptionRemoved", this._onQ2SubRemoved);
8679
- }
8680
-
8681
- this._quotes2 = subs;
8682
-
8683
- if (this._quotes2) {
8684
- this._quotes2["addEventListener"]("dataChanged", this._onQ2DataChanged);
8685
- this._quotes2["addEventListener"]("subscriptionAdded", this._onQ2SubAdded);
8686
- this._quotes2["addEventListener"]("subscriptionRemoved", this._onQ2SubRemoved);
8687
- }
8688
- };
8673
+ DataCache.prototype.setSubscriptions = function () {};
8689
8674
 
8690
- /**
8691
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.This API supports only Quotes2's
8692
- * "Subscriptions" object.
8675
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8693
8676
  * @public
8694
- * @return {Object} subs Subscriptions object from JET.Quotes2
8677
+ * @ignore
8678
+ * @return {Object} Always returns null
8695
8679
  */
8696
- DataCache.prototype.getSubscriptions = function () {
8697
- return this._quotes2;
8698
- };
8680
+ DataCache.prototype.getSubscriptions = function () { return null; };
8699
8681
 
8700
- /**
8701
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8682
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8702
8683
  * @public
8703
- * @param {Object} sub Subscription object from JET.Quote
8704
- * @param {string=} opt_primaryRic Main RIC for creating Id or recalling subscription. This is because subscription
8705
- * object does not provide a way to access its data
8706
- * @param {Object=} opt_values Initial values
8684
+ * @ignore
8707
8685
  */
8708
- DataCache.prototype.addSubscription = function (sub, opt_primaryRic, opt_values) {
8709
- if (this.getSubscription(sub["id"])) {
8710
- return;
8711
- }
8712
-
8713
- let internalSub = {"s": sub, "rics": {}};
8714
-
8715
- this._subs[sub["id"]] = internalSub;
8686
+ DataCache.prototype.addSubscription = function () {};
8716
8687
 
8717
- if (!this._quotes2) {
8718
- sub["onNewRow"](this._onInsert);
8719
- sub["onUpdate"](this._onUpdate);
8720
- sub["onRemoveRow"](this._onDelete);
8721
- }
8722
-
8723
- if (opt_primaryRic) {
8724
- internalSub["primary"] = opt_primaryRic;
8725
-
8726
- if (!opt_values) {
8727
- opt_values = {};
8728
- }
8729
-
8730
- this._onInsert(sub, opt_primaryRic, opt_values);
8731
- }
8732
- };
8733
-
8734
- /**
8735
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8688
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8736
8689
  * @public
8737
- * @param {Object} sub Subscription object from JET.Quote
8690
+ * @ignore
8738
8691
  */
8739
- DataCache.prototype.removeSubscription = function (sub) { // All RICs associated to the subscription are removed
8740
- let subId = sub["id"];
8692
+ DataCache.prototype.removeSubscription = function () {};
8741
8693
 
8742
- if (!sub || !this._subs[subId]) {
8743
- return;
8744
- }
8745
-
8746
- if (!this._quotes2) {
8747
- sub["stop"]();
8748
- }
8749
-
8750
- let rics = this._subs[subId]["rics"];
8751
-
8752
- for (let ric in rics) {
8753
- this.setRowData(subId + ric, null); // No subscription attached
8754
- }
8755
-
8756
- delete this._subs[subId];
8757
- };
8758
-
8759
- /**
8760
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8694
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8761
8695
  * @public
8696
+ * @ignore
8762
8697
  */
8763
- DataCache.prototype.startAllSubscriptions = function () {
8764
- if (this._quotes2) {
8765
- this._quotes2["start"]();
8766
- } else {
8767
- for (let key in this._subs) {
8768
- this._subs[key]["s"]["start"]();
8769
- }
8770
- }
8771
- };
8698
+ DataCache.prototype.startAllSubscriptions = function () {};
8772
8699
 
8773
- /**
8774
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8700
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8775
8701
  * @public
8702
+ * @ignore
8776
8703
  */
8777
- DataCache.prototype.stopAllSubscriptions = function () {
8778
- if (this._quotes2) {
8779
- this._quotes2["stop"]();
8780
- } else {
8781
- for (let key in this._subs) {
8782
- this._subs[key]["s"]["stop"]();
8783
- }
8784
- }
8785
- };
8704
+ DataCache.prototype.stopAllSubscriptions = function () {};
8786
8705
 
8787
- /**
8706
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8788
8707
  * @public
8789
- * @param {string} sub_id
8790
- * @return {Object} Subscription object from JET.Quote
8708
+ * @ignore
8709
+ * @return {Object} Always returns null
8791
8710
  */
8792
- DataCache.prototype.getSubscription = function (sub_id) {
8793
- return (this._subs[sub_id]) ? this._subs[sub_id]["s"] : null;
8794
- };
8711
+ DataCache.prototype.getSubscription = function () { return null; };
8795
8712
 
8796
- /**
8713
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8797
8714
  * @public
8798
- * @param {string} sub_id
8799
- * @return {string} ric that has been input when calling addSubscription
8715
+ * @ignore
8716
+ * @return {string} Always returns empty string
8800
8717
  */
8801
- DataCache.prototype.getPrimaryRic = function (sub_id) {
8802
- let subDef = this._subs[sub_id];
8803
- if (subDef) {
8804
- return subDef["primary"];
8805
- }
8806
- return "";
8807
- };
8718
+ DataCache.prototype.getPrimaryRic = function () { return ""; };
8808
8719
 
8809
- /**
8810
- * @public
8720
+ /** @public
8811
8721
  * @param {boolean=} opt_suppressEvent
8812
8722
  * @fires DataCache#dataChanged
8813
8723
  */
8814
- DataCache.prototype.clearAllData = function (opt_suppressEvent) { // All subscriptions are also removed
8815
- if (this._quotes2) {
8816
- this._quotes2["removeAllSubscriptions"]();
8817
- } else {
8818
- this.stopAllSubscriptions();
8819
- }
8820
-
8821
- this._subs = {};
8724
+ DataCache.prototype.clearAllData = function (opt_suppressEvent) {
8822
8725
  this._rows = {};
8823
8726
 
8824
8727
  if (!opt_suppressEvent) {
@@ -8862,28 +8765,12 @@ DataCache.prototype.getData = function (rid, cid) {
8862
8765
  return (row) ? row[cid] : null;
8863
8766
  };
8864
8767
 
8865
- /**
8866
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8768
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8867
8769
  * @public
8868
- * @return {Object.<string, Array.<string>>} Map of Array of subscription object
8770
+ * @ignore
8771
+ * @return {Object.<string, Array.<string>>} Always returns null
8869
8772
  */
8870
- DataCache.prototype.getAllRics = function () { // Slow
8871
- let ricMap = {};
8872
-
8873
- for (let subId in this._subs) {
8874
- let rics = this._subs[subId]["rics"];
8875
-
8876
- for (let ric in rics) {
8877
- if (!ricMap[ric]) {
8878
- ricMap[ric] = [];
8879
- }
8880
-
8881
- ricMap[ric].push(subId);
8882
- }
8883
- }
8884
-
8885
- return ricMap; // No duplicate ric
8886
- };
8773
+ DataCache.prototype.getAllRics = function () { return null; };
8887
8774
 
8888
8775
  /**
8889
8776
  * @public
@@ -9082,27 +8969,22 @@ DataCache.prototype.cloneRowData = function (rid) {
9082
8969
  /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
9083
8970
  * @public
9084
8971
  * @ignore
9085
- * @suppress {checkTypes}
9086
8972
  */
9087
8973
  DataCache.prototype.addStaticFields = function () {};
9088
8974
 
9089
- /**
9090
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8975
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
9091
8976
  * @public
9092
8977
  * @ignore
9093
- * @suppress {checkTypes}
9094
8978
  */
9095
8979
  DataCache.prototype.removeStaticFields = function () {};
9096
8980
 
9097
- /**
9098
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8981
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
9099
8982
  * @public
9100
8983
  * @ignore
9101
8984
  */
9102
8985
  DataCache.prototype.resetStaticFields = function () {};
9103
8986
 
9104
- /**
9105
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
8987
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
9106
8988
  * @public
9107
8989
  * @ignore
9108
8990
  */
@@ -9143,40 +9025,29 @@ DataCache.prototype.log = function (opt_options) {
9143
9025
  console.table(this.dump(opt_options));
9144
9026
  };
9145
9027
 
9146
- //#region ADC
9147
9028
  /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
9148
9029
  * @public
9149
9030
  * @ignore
9150
- * @param {string} userId
9151
- * @param {string} productId
9152
- * @param {string} url
9153
- * @param {string=} opt_lang
9154
9031
  */
9155
- DataCache.prototype.setDataCloudSettings = function (userId, productId, url, opt_lang) {};
9032
+ DataCache.prototype.setDataCloudSettings = function () {};
9156
9033
 
9157
- /**
9158
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
9034
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
9159
9035
  * @public
9160
9036
  * @ignore
9161
9037
  */
9162
9038
  DataCache.prototype.getDataCloudFields = function () {};
9163
9039
 
9164
- /**
9165
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
9040
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
9166
9041
  * @public
9167
9042
  * @ignore
9168
- * @param {Array.<string>|string} fields
9169
9043
  */
9170
- DataCache.prototype.addDataCloudFields = function (fields) {};
9044
+ DataCache.prototype.addDataCloudFields = function () {};
9171
9045
 
9172
- /**
9173
- * Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
9046
+ /** Deprecated. Built-in Data Service is deprecated due to the lack of flexibility.
9174
9047
  * @public
9175
9048
  * @ignore
9176
- * @param {string} field
9177
9049
  */
9178
- DataCache.prototype.removeDataCloudField = function (field) {};
9179
- //#endregion ADC
9050
+ DataCache.prototype.removeDataCloudField = function () {};
9180
9051
  //#endregion Public
9181
9052
 
9182
9053
  /**
@@ -9313,162 +9184,6 @@ DataCache.constructTable = function (dataset, opt_options, opt_rowIds) {
9313
9184
  };
9314
9185
 
9315
9186
 
9316
- //#region Private
9317
- /**
9318
- * For Quotes2 only
9319
- * @private
9320
- * @param {string} subId
9321
- * @param {string} ric
9322
- * @param {Object.<string, *>} values
9323
- */
9324
- DataCache.prototype._insertRic = function (subId, ric, values) {
9325
- // HACK: Some chain may have 0# symbol in there chain index (e.g. 0#CL:)
9326
- ric = ric.replace("0#", "");
9327
-
9328
- let rid = subId + ric;
9329
-
9330
- let rowData = this.getRowData(rid);
9331
- if (!rowData) { // Ensure that we have subscription id and ric from Quotes2
9332
- let tmp = values;
9333
-
9334
- values = {}; // Clone a new object for duplicated ric
9335
-
9336
- for (let key in tmp) { // Slow
9337
- values[key] = tmp[key];
9338
- }
9339
-
9340
- values["SUB_ID"] = subId;
9341
- values["RIC"] = ric;
9342
- } else {
9343
- let rowDef = rowData["ROW_DEF"];
9344
- if(rowDef && rowDef.isChain()){
9345
- values["SUB_ID"] = subId;
9346
- }
9347
- }
9348
-
9349
- this.setRowData(rid, values);
9350
- };
9351
-
9352
- /**
9353
- * @private
9354
- * @param {Object} e
9355
- */
9356
- DataCache.prototype._onQ2DataChanged = function (e) {
9357
- let subId = e["subId"];
9358
- let ric = e["ric"];
9359
- let values = /** @type{Object.<string, *>} */(e["values"]);
9360
-
9361
- if (values) {
9362
- this._insertRic(subId, ric, values);
9363
- } else { // Remove ric
9364
- delete this._subs[subId]["rics"][ric];
9365
-
9366
- this.setRowData(subId + ric, null);
9367
- }
9368
- };
9369
-
9370
- /**
9371
- * @private
9372
- * @param {Object} e
9373
- */
9374
- DataCache.prototype._onQ2SubAdded = function (e) {
9375
- let subs = e["subs"];
9376
- let len = subs.length;
9377
-
9378
- for (let i = 0; i < len; ++i) {
9379
- let sub = subs[i];
9380
-
9381
- // chain subId fires twice, one with "_ci_" and one without "_ci_"
9382
- // the subId with "_ci_" should be ignore
9383
- if(sub["id"].indexOf("_ci_") < 0){
9384
- this.addSubscription(sub, sub["ric"]);
9385
- }
9386
- }
9387
- };
9388
-
9389
- /**
9390
- * @private
9391
- * @param {Object} e
9392
- */
9393
- DataCache.prototype._onQ2SubRemoved = function (e) {
9394
- let subs = e["subs"];
9395
- let len = subs.length;
9396
-
9397
- for (let i = 0; i < len; ++i) {
9398
- let sub = subs[i];
9399
-
9400
- // chain subId fires twice, one with "_ci_" and one without "_ci_"
9401
- // the subId with "_ci_" should be ignore
9402
- if(sub["id"].indexOf("_ci_") < 0){
9403
- this.removeSubscription(sub);
9404
- }
9405
- }
9406
- };
9407
-
9408
- /**
9409
- * @private
9410
- * @param {Object} sub Subscription object from JET.Quote
9411
- * @param {string} ric
9412
- * @param {Object.<string, *>} values
9413
- */
9414
- DataCache.prototype._onInsert = function (sub, ric, values/*, rowN*/) {
9415
- let subId = sub["id"];
9416
-
9417
- if (this._quotes2) {
9418
- this._insertRic(subId, ric, values);
9419
- } else {
9420
- this.setRowData(subId + ric, values, {"subscription": sub, "ric": ric});
9421
- }
9422
- };
9423
-
9424
- /**
9425
- * @private
9426
- * @function
9427
- */
9428
- DataCache.prototype._onUpdate = DataCache.prototype._onInsert;
9429
-
9430
- /**
9431
- * This is a legacy code and should be deprecated
9432
- * @private
9433
- * @param {Object} sub Subscription object from JET.Quote
9434
- * @param {string} ric
9435
- * @param {Array.<string, *>} values
9436
- */
9437
- DataCache.prototype._onDelete = function (sub, ric, values/*, rowN*/) {
9438
- delete this._subs[sub["id"]]["rics"][ric];
9439
-
9440
- // We cannot cache event arguments because user may want to collect all the updates
9441
- this.setRowData(sub["id"] + ric, null, {"subscription": sub, "ric": ric});
9442
- };
9443
-
9444
- /** @protected
9445
- * @ignore
9446
- * @type {!Object.<string, Object>}
9447
- */
9448
- DataCache.prototype._rows;
9449
-
9450
- /**
9451
- * @private
9452
- * @type {!Object.<string, Object>}
9453
- */
9454
- DataCache.prototype._subs;
9455
-
9456
- /**
9457
- * @private
9458
- * @type {Object}
9459
- */
9460
- DataCache.prototype._quotes2 = null;
9461
-
9462
- /** @protected
9463
- * @ignore
9464
- * @type {boolean}
9465
- */
9466
- DataCache.prototype._composing = false;
9467
-
9468
- //#endregion Private
9469
-
9470
- DataCache._proto = DataCache.prototype;
9471
-
9472
9187
  /* harmony default export */ var data_DataCache = (DataCache);
9473
9188
 
9474
9189
 
@@ -12978,20 +12693,32 @@ const ROW_TYPES = {
12978
12693
  */
12979
12694
  const ROW_ID_PATTERN = /^_[^_]+_$/;
12980
12695
 
12696
+ /** @private
12697
+ * @function
12698
+ * @param {Object} obj
12699
+ * @returns {!Object} Always returns a new object
12700
+ */
12701
+ let _cloneObject = function(obj) {
12702
+ let newObj = {};
12703
+ for(let key in obj) {
12704
+ newObj[key] = obj[key];
12705
+ }
12706
+ return newObj;
12707
+ };
12708
+
12981
12709
  /** @constructor
12982
12710
  * @param {RowDefinition~Options=} rowOptions
12983
12711
  */
12984
12712
  let RowDefinition = function(rowOptions) {
12985
12713
  this._changes = {};
12986
- if(rowOptions && rowOptions["segmentId"]) { // This row will be classification header row
12987
- this._dataId = this._rowId = rowOptions["segmentId"];
12714
+ if(rowOptions && rowOptions["segmentId"]) { // This row will be classified header row (subsegment header row)
12715
+ this._rowId = rowOptions["segmentId"];
12988
12716
  this._autoGenerated = true;
12989
12717
  this._subSegment = true;
12990
12718
  return;
12991
12719
  }
12992
12720
 
12993
12721
  this._rowId = "_" + RowDefinition._runningId++ + "_";
12994
- this._dataId = this._rowId;
12995
12722
 
12996
12723
  if(rowOptions) {
12997
12724
  if(rowOptions["asConstituent"]) { // Create row definition as a constituent of a chain
@@ -13044,10 +12771,6 @@ RowDefinition.prototype._realTime = true;
13044
12771
  * @private
13045
12772
  */
13046
12773
  RowDefinition.prototype._rowId = ""; // Row Id must be unique
13047
- /** @type {string}
13048
- * @private
13049
- */
13050
- RowDefinition.prototype._dataId = ""; // Data id can be different from rowId for constituents of a chain
13051
12774
  /** @type {boolean}
13052
12775
  * @private
13053
12776
  */
@@ -13056,6 +12779,11 @@ RowDefinition.prototype._userId = false;
13056
12779
  * @private
13057
12780
  */
13058
12781
  RowDefinition.prototype._dc = null;
12782
+ /** Quotes2 subscription object
12783
+ * @type {Object}
12784
+ * @private
12785
+ */
12786
+ RowDefinition.prototype._subs = null;
13059
12787
  /** @type {DataView}
13060
12788
  * @private
13061
12789
  */
@@ -13131,22 +12859,20 @@ RowDefinition.prototype.dispose = function() {
13131
12859
  this._children = null;
13132
12860
  }
13133
12861
 
12862
+ if(this._dc) {
12863
+ this._dc.setRowData(this._rowId, null); // Clear all data held by this row def
12864
+ this._dc = null;
12865
+ }
13134
12866
  this._staticValues = null; // Static values contain user data
13135
12867
  this._parent = null; // WARNING: This does not impact children count of the parent. A child must be destroyed by its parent only
13136
12868
  this._depthLevel = 0;
13137
12869
  this.unsubscribeForUpdates();
13138
- if(this._dc) {
13139
- let rowData = this.getRowData();
13140
- if(rowData) {
13141
- rowData[ROW_DEF] = null;
13142
- }
13143
- this._dc = null;
13144
- }
13145
- if(this._view) {
13146
- this._view = null;
13147
- }
13148
- this._rowId = this._dataId = "";
12870
+ this._subs = null;
12871
+ this._view = null; // WARNING: This does not remove this row from the UI view
12872
+
12873
+ this._subId = this._rowId = "";
13149
12874
  this._userId = false;
12875
+ this._autoGenerated = false;
13150
12876
  this._userModel = null;
13151
12877
  };
13152
12878
  /** @public
@@ -13169,7 +12895,7 @@ RowDefinition.prototype.initialize = function(rowOptions) {
13169
12895
  if(userRowId.match(ROW_ID_PATTERN)) {
13170
12896
  console.warn("Please change the rowId format to avoid duplicated rows' id causing unexpected behavior.");
13171
12897
  } else {
13172
- this._rowId = this._dataId = userRowId;
12898
+ this._rowId = userRowId;
13173
12899
  this._userId = true;
13174
12900
  }
13175
12901
  }
@@ -13225,7 +12951,7 @@ RowDefinition.prototype.initialize = function(rowOptions) {
13225
12951
 
13226
12952
  let symbol = this._ric || this._chainRic;
13227
12953
  if(symbol || this._permId){
13228
- this.setContent(symbol, extractedOptions); // this._dataId is modified
12954
+ this.setContent(symbol, extractedOptions);
13229
12955
  }
13230
12956
 
13231
12957
  val = rowOptions["values"];
@@ -13234,28 +12960,20 @@ RowDefinition.prototype.initialize = function(rowOptions) {
13234
12960
  this.setStaticRowData(val, rowOptions["fields"]);
13235
12961
  }
13236
12962
  };
13237
- /** @private
12963
+ /** @description Constituents will have subscription id, but have no subscription. It's row id will be different from subscription id. It will have a reference to its parent. It cannot be generated by themselve -- always be autogenerated.
12964
+ * @private
13238
12965
  * @param {!Object} rowOptions
13239
12966
  */
13240
12967
  RowDefinition.prototype._initializeAsConstituent = function(rowOptions) {
13241
12968
  this._autoGenerated = true;
13242
12969
  let parentDef = /** @type{RowDefinition} */(rowOptions["parent"]);
13243
12970
  if(this.setParent(parentDef)) {
13244
- this._dataId = /** @type{string} */(rowOptions["dataId"]); // Constituent will have the same subId as its parent but with different ric
13245
12971
  this._ric = /** @type{string} */(rowOptions["ric"]);
13246
12972
  this._dc = parentDef._dc; // Parent chain must have data cache
13247
- if(this._dc) {
13248
- let rowData = this.getRowData(); // Do not trigger any data update
13249
- if(rowData) { // Row data from data cache must exist beforehand
13250
- rowData[ROW_DEF] = this; // This is for easy referencing from data streaming, also for preventing duplication
13251
- }
13252
- }
13253
- }
13254
- let val = rowOptions["values"];
13255
- // eslint-disable-next-line no-undefined
13256
- if(val !== undefined) {
13257
- this.setStaticRowData(val, rowOptions["fields"]);
12973
+ this._subId = parentDef._subId; // Child constituent uses the same subscription as its parent
13258
12974
  }
12975
+ this._staticValues = rowOptions["values"] || null;
12976
+ this.resetRowData();
13259
12977
  };
13260
12978
  /** @private
13261
12979
  * @param {DataView} view
@@ -13310,9 +13028,9 @@ RowDefinition.prototype.setContent = function(userInput, extractedOptions) {
13310
13028
  }
13311
13029
 
13312
13030
  let dirty = (this._userInput !== userInput);
13313
- let permId = extractedOptions["permId"];
13031
+ let permId = extractedOptions["permId"] || "";
13314
13032
  if(this._permId !== permId){
13315
- this._permId = permId || "";
13033
+ this._permId = permId;
13316
13034
  dirty = true;
13317
13035
  }
13318
13036
  if(!dirty) {
@@ -13329,10 +13047,7 @@ RowDefinition.prototype.setContent = function(userInput, extractedOptions) {
13329
13047
  let dv = this._view;
13330
13048
  let stalledSorting = _stallSorting(dv, realtimeRow && asChain, false); // To preserve current position of the segment/chain
13331
13049
 
13332
- if(!this.unsubscribeForUpdates()){
13333
- this._clearStaticData();
13334
- }
13335
- this.resetUpdates(); // Remove all previous data updates because a new content is just entered
13050
+ this.unsubscribeForUpdates(); // Static data remains intact
13336
13051
 
13337
13052
  this._userInput = userInput;
13338
13053
  let collapsed = extractedOptions["collapsed"];
@@ -13346,9 +13061,6 @@ RowDefinition.prototype.setContent = function(userInput, extractedOptions) {
13346
13061
  this._isChain = asChain != null ? asChain : null; // this could be null or undefined
13347
13062
  this._chainRic = chainRic || "";
13348
13063
  }
13349
- // A symbol can be either RIC or permId
13350
- // JET/RTK will generate data id to be rowId (given from this rowDef) + ric
13351
- this._dataId = this._rowId + this.getSymbol();
13352
13064
 
13353
13065
  if(dv) {
13354
13066
  let segmentId = dv.getSegmentParentRowId(this._rowId);
@@ -13367,27 +13079,18 @@ RowDefinition.prototype.setContent = function(userInput, extractedOptions) {
13367
13079
  dv.setSegmentSeparator(this._rowId, true);
13368
13080
  }
13369
13081
 
13370
- if(collapsed !== this.isChainCollapsed()) {
13082
+ if(collapsed !== this.isChainCollapsed()) { // WARNING: This is not optimizsed
13371
13083
  dv.collapseSegment(this._rowId, collapsed);
13372
13084
  }
13373
13085
  this._collapsed = null;
13374
13086
 
13375
13087
  _stallSorting(dv, false, stalledSorting);
13376
13088
  if(segmentId) { // If data id is changed and the row is a child of a segment, then segment child data id must be updated
13377
- dv.addSegmentChild(segmentId, this._rowId, this._dataId);
13089
+ dv.addSegmentChild(segmentId, this._rowId);
13378
13090
  }
13379
13091
  }
13380
13092
 
13381
- if(!this.subscribeForUpdates()) {
13382
- if(this._dc) {
13383
- // This will work for runtime ric modification, but not for first initilization.
13384
- // Avoid losing the ROW_DEF pointer.
13385
- let rowData = {};
13386
- rowData[ROW_DEF] = this; // Enable tracking back and updating data
13387
- rowData["X_RIC_NAME"] = this.getDisplayText();
13388
- this.setRowData(rowData);
13389
- }
13390
- }
13093
+ this.subscribeForUpdates();
13391
13094
  return true;
13392
13095
  };
13393
13096
  /** @public
@@ -13499,12 +13202,12 @@ RowDefinition.prototype.getConfigObject = function(rowOptions) {
13499
13202
 
13500
13203
  return obj;
13501
13204
  };
13502
- /** Since an index chain (e.g. .FTSE) can automatically produce rows for its constituent, we need to separate rowId and dataId, so that the constituents still use the same data Id as that of its parent.
13205
+ /** Data id is deprecated
13503
13206
  * @public
13504
- * @return {string} Data Id will never be empty string unless the row has been removed
13207
+ * @return {string} Always return empty string
13505
13208
  */
13506
13209
  RowDefinition.prototype.getDataId = function() {
13507
- return this._dataId;
13210
+ return "";
13508
13211
  };
13509
13212
  /** @public
13510
13213
  * @return {string}
@@ -13540,26 +13243,16 @@ RowDefinition.prototype.getType = function() {
13540
13243
  /** This method should always be called right after the initialization
13541
13244
  * @public
13542
13245
  * @param {DataCache} dataSource
13246
+ * @param {Object=} subs Quotes2 subscription object
13543
13247
  */
13544
- RowDefinition.prototype.setDataSource = function(dataSource) {
13248
+ RowDefinition.prototype.setDataSource = function(dataSource, subs) {
13545
13249
  this._dc = dataSource || null;
13546
- if(!this._dc) {
13547
- return;
13548
- }
13549
-
13550
- let rowData = this.getRowData();
13551
- if(!rowData) {
13552
- rowData = {};
13553
- rowData[ROW_DEF] = this; // Enable tracking back and updating data
13554
- rowData["X_RIC_NAME"] = this.getDisplayText();
13555
- this.setRowData(rowData); // TODO: This will dispatch dataChanged event and caused update to be added, which should not happen
13556
- }
13557
13250
 
13558
- // Add static value to the new source
13559
- if(this._staticValues) {
13560
- this.setRowData(this._staticValues);
13251
+ if(this._dc) {
13252
+ this.setRowData(_cloneObject(this._staticValues)); // Trigger data change
13561
13253
  }
13562
13254
 
13255
+ this._subs = subs || null;
13563
13256
  // This will work for runtime row insertion, but not for first initilization.
13564
13257
  this.subscribeForUpdates();
13565
13258
  };
@@ -13574,14 +13267,14 @@ RowDefinition.prototype.getDataSource = function() {
13574
13267
  * @return {Object} rowData
13575
13268
  */
13576
13269
  RowDefinition.prototype.getRowData = function() {
13577
- return this._dc ? this._dc.getRowData(this._dataId) : {};
13270
+ return this._dc ? this._dc.getRowData(this._rowId) : {};
13578
13271
  };
13579
13272
  /** @public
13580
13273
  * @param {string} field
13581
13274
  * @return {*} data
13582
13275
  */
13583
13276
  RowDefinition.prototype.getData = function(field) {
13584
- return this._dc ? this._dc.getData(this._dataId, field) : null;
13277
+ return this._dc ? this._dc.getData(this._rowId, field) : null;
13585
13278
  };
13586
13279
 
13587
13280
  /** This method replaces all existing static data by the given data -- all existing static data are removed.
@@ -13606,7 +13299,7 @@ RowDefinition.prototype.setStaticRowData = function(data, indexToFieldMap) {
13606
13299
  * @return {Object.<string, *>}
13607
13300
  */
13608
13301
  RowDefinition.prototype._cloneStaticRowData = function() {
13609
- return this._staticValues ? cloneObject(this._staticValues) : null;
13302
+ return this._staticValues ? _cloneObject(this._staticValues) : null;
13610
13303
  };
13611
13304
  /** @public
13612
13305
  * @param {string} field
@@ -13676,7 +13369,15 @@ RowDefinition.prototype.cloneRowData = function(obj, exceptionObj) {
13676
13369
  */
13677
13370
  RowDefinition.prototype.setRowData = function(data) {
13678
13371
  if(this._dc) {
13679
- this._dc.setRowData(this._dataId, data);
13372
+ this._dc.setRowData(this._rowId, data);
13373
+ }
13374
+ };
13375
+ /** @public
13376
+ */
13377
+ RowDefinition.prototype.resetRowData = function() {
13378
+ if(this._dc) {
13379
+ this._dc.setRowData(this._rowId, null);
13380
+ this._dc.setRowData(this._rowId, _cloneObject(this._staticValues)); // Row data is guaranteed to be existed
13680
13381
  }
13681
13382
  };
13682
13383
  /** @public
@@ -13685,18 +13386,20 @@ RowDefinition.prototype.setRowData = function(data) {
13685
13386
  */
13686
13387
  RowDefinition.prototype.setData = function(field, value) {
13687
13388
  if(this._dc) {
13688
- this._dc.setData(this._dataId, field, value);
13389
+ this._dc.setData(this._rowId, field, value);
13689
13390
  }
13690
13391
  };
13691
13392
  /** @private
13692
13393
  */
13693
13394
  RowDefinition.prototype._clearStaticData = function() {
13694
- if(this._staticValues) {
13695
- for(let key in this._staticValues) {
13696
- this._staticValues[key] = null;
13697
- }
13395
+ let staticValues = this._staticValues;
13396
+ if(staticValues) {
13698
13397
  if(this._dc) {
13699
- this._dc.setRowData(this._dataId, this._staticValues);
13398
+ let obj = {};
13399
+ for(let key in staticValues) {
13400
+ obj[key] = null;
13401
+ }
13402
+ this._dc.setRowData(this._rowId, obj);
13700
13403
  }
13701
13404
  this._staticValues = null;
13702
13405
  }
@@ -13734,7 +13437,7 @@ RowDefinition.prototype.getDisplayText = function() {
13734
13437
  return this._label;
13735
13438
  }
13736
13439
 
13737
- if(this._ric) {
13440
+ if(this._ric) { // Use chainRic instead if this is a chain
13738
13441
  return this._ric;
13739
13442
  }
13740
13443
 
@@ -13764,6 +13467,12 @@ RowDefinition.prototype.isChain = function() {
13764
13467
  return this._isChain;
13765
13468
  };
13766
13469
  /** @public
13470
+ * @return {boolean}
13471
+ */
13472
+ RowDefinition.prototype.isConstituent = function() {
13473
+ return (this._autoGenerated && this._subId && this._rowId !== this._subId) ? true : false;
13474
+ };
13475
+ /** @public
13767
13476
  * @function
13768
13477
  * @param {RowDefinition} rowDef
13769
13478
  * @return {boolean}
@@ -13822,19 +13531,23 @@ RowDefinition.prototype.isRealTimeRow = function() {
13822
13531
  };
13823
13532
 
13824
13533
  /** @public
13534
+ * @param {Object=} subs
13825
13535
  * @return {boolean} If a subscription is made, return true.
13826
13536
  */
13827
- RowDefinition.prototype.subscribeForUpdates = function() {
13828
- if(!this.isRealTimeRow() && !this.getPermId()) {
13829
- return false;
13537
+ RowDefinition.prototype.subscribeForUpdates = function(subs) {
13538
+ if(subs) {
13539
+ this._subs = subs;
13540
+ } else {
13541
+ subs = this._subs;
13830
13542
  }
13831
-
13832
- let subs = this._dc ? this._dc.getSubscriptions() : null;
13833
13543
  if(!subs) {
13834
13544
  return false;
13835
13545
  }
13546
+ if(!this.isRealTimeRow() && !this.getPermId()) {
13547
+ return false;
13548
+ }
13836
13549
  // TODO: Check if the same subscription is being made.
13837
- let prevRowData = this.unsubscribeForUpdates();
13550
+ this.unsubscribeForUpdates();
13838
13551
 
13839
13552
  if(this.isChain()) {
13840
13553
  let symbol = this._chainRic;
@@ -13852,57 +13565,51 @@ RowDefinition.prototype.subscribeForUpdates = function() {
13852
13565
  this._subId = subs["addRic"](this._ric, this._rowId);
13853
13566
  }
13854
13567
 
13855
- if(prevRowData) {
13856
- this._dc.setRowData(this._dataId, prevRowData); // TODO: We may need to create a new object instead of prevRowData for data correctness
13857
- } else {
13858
- this._dc.setRowData(this._dataId, {"X_RIC_NAME": this.getDisplayText(), "ROW_DEF": this}); // Trigger data update immediately
13859
- }
13568
+ let xRicName = this.getDisplayText(); // WARNING: This does not cover real-time X_RIC_NAME updates
13569
+ this.setRowData({"X_RIC_NAME": xRicName}); // Trigger data update immediately
13570
+
13860
13571
  return true;
13861
13572
  };
13862
- /** @public
13863
- * @returns {*}
13573
+ /** Unsubscribe existing real-time data service. Static data is maintained
13574
+ * @public
13575
+ * @returns {null} Always return null
13864
13576
  */
13865
13577
  RowDefinition.prototype.unsubscribeForUpdates = function() {
13866
- if(!this._subId) {
13867
- return;
13578
+ if(this.isSubscribing()) { // Only normal real-time rows and chains have both subId and subscription object
13579
+ this._subs["removeSubscription"](this._subId);
13580
+ this._subId = "";
13581
+ this.resetUpdates();
13582
+ this.resetRowData(); // Real-time data is removed while static data is maintained
13868
13583
  }
13869
-
13870
- let subs = this._dc.getSubscriptions();
13871
- let prevRowData = this.getRowData();
13872
-
13873
- subs["removeSubscription"](this._subId);
13874
- this._subId = "";
13875
- this.resetUpdates();
13876
- // TODO: Reset only if this is the last ric
13877
- this._dc.setRowData(this._dataId, null); // Trigger data update immediately
13878
- this._clearStaticData();
13879
- // eslint-disable-next-line consistent-return
13880
- return prevRowData;
13584
+ return null;
13881
13585
  };
13882
13586
  /** @public
13883
13587
  * @return {boolean}
13884
13588
  */
13885
13589
  RowDefinition.prototype.isSubscribing = function() {
13886
- return this._subId ? true : false;
13590
+ return (this._subId && this._subs) ? true : false;
13591
+ };
13592
+ /** @public
13593
+ * @return {string}
13594
+ */
13595
+ RowDefinition.prototype.getSubId = function() {
13596
+ return this._subId;
13887
13597
  };
13888
13598
 
13889
13599
  /** Take event argument from streaming update with "changes" array property
13890
13600
  * @public
13891
- * @param {Object} e Object with changes property
13601
+ * @param {Object} changes
13892
13602
  * @return {boolean} Returns true if there is any change
13893
13603
  */
13894
- RowDefinition.prototype.addUpdate = function(e) {
13895
- if(e) {
13896
- let changes = e["changes"];
13897
- if(changes) {
13898
- let dirty = 0;
13899
- for(let field in changes) {
13900
- this._changes[field] = dirty = 1;
13901
- }
13902
- if(dirty) {
13903
- ++this._updateCount;
13904
- return true;
13905
- }
13604
+ RowDefinition.prototype.addUpdate = function(changes) {
13605
+ if(changes) {
13606
+ let dirty = 0;
13607
+ for(let field in changes) {
13608
+ this._changes[field] = dirty = 1;
13609
+ }
13610
+ if(dirty) {
13611
+ ++this._updateCount;
13612
+ return true;
13906
13613
  }
13907
13614
  }
13908
13615
  return false;
@@ -13925,27 +13632,27 @@ RowDefinition.prototype.resetUpdates = function() {
13925
13632
 
13926
13633
  /** @public
13927
13634
  * @param {DataView} view
13928
- * @param {string=} destRowId Destination position where the row will be placed BEFORE the specified position.
13635
+ * @param {string=} destRowId Destination position where the row will be placed BEFORE the specified position
13636
+ * @returns {boolean} Returns true for successful registration
13929
13637
  */
13930
13638
  RowDefinition.prototype.registerToView = function(view, destRowId) {
13931
13639
  if(!view || this._view === view) {
13932
- return; // Already in the view
13640
+ return false; // Already in the view
13933
13641
  }
13934
- this._view = view;
13935
13642
 
13936
- let rowId = this.getRowId();
13937
- if(view.getRowData(rowId)) {
13938
- console.warn("Duplicated rows' id.");
13939
- return;
13643
+ this._view = view;
13644
+ let rowId = this._rowId;
13645
+ let rowData = view.getRowData(rowId);
13646
+ if(rowData && rowData[ROW_DEF]) {
13647
+ console.warn("Duplicate row id detected");
13648
+ return false;
13940
13649
  }
13941
13650
 
13942
- let rowData = null;
13943
13651
  if(this._subSegment) {
13944
- rowData = this._view.getRowData(this.getRowId());
13945
- if(rowData) {
13946
- rowData[ROW_DEF] = this; // no event trigger
13652
+ if(rowData) { // Row data for sub segment has been created by data view
13653
+ rowData[ROW_DEF] = this; // It only needs to register row def to the row data
13947
13654
  }
13948
- return;
13655
+ return true;
13949
13656
  }
13950
13657
 
13951
13658
  rowData = {};
@@ -13958,7 +13665,13 @@ RowDefinition.prototype.registerToView = function(view, destRowId) {
13958
13665
  if(parentRowId) {
13959
13666
  if(isSegment) { // A chain or a segment cannot be put inside another segment
13960
13667
  destRowId = _getEndOfSegmentRowId(view, destRowId);
13961
- } // else { // Normal row is inserted into a segment
13668
+ } else if(!this.isConstituent()) { // Normal row cannot be put inside another chain
13669
+ let parentRowDef = view.getData(parentRowId, ROW_DEF);
13670
+ if(parentRowDef.isChain()) {
13671
+ parentRowId = null;
13672
+ destRowId = _getEndOfSegmentRowId(view, destRowId);
13673
+ } // else { // Normal row is inserted into a segment
13674
+ } // Constituent can be inserted inside a chain
13962
13675
  }
13963
13676
  }
13964
13677
 
@@ -13973,8 +13686,10 @@ RowDefinition.prototype.registerToView = function(view, destRowId) {
13973
13686
  this._collapsed = null;
13974
13687
  }
13975
13688
  } else if(!this._parent && parentRowId) { // Constituent cannot be added to another segment
13976
- view.addSegmentChild(parentRowId, rowId, this._dataId);
13689
+ view.addSegmentChild(parentRowId, rowId);
13977
13690
  }
13691
+
13692
+ return true;
13978
13693
  };
13979
13694
  /** @private
13980
13695
  * @param {Array.<string>=} rowIds
@@ -13991,7 +13706,9 @@ RowDefinition.prototype._deregisterFromView = function(rowIds) {
13991
13706
  }
13992
13707
  return "";
13993
13708
  };
13994
- /** @public
13709
+ /** Deprecated.
13710
+ * @public
13711
+ * @ignore
13995
13712
  * @function
13996
13713
  * @param {Array.<string>} rowIds
13997
13714
  * @param {RowDefinition} rowDef
@@ -14008,77 +13725,74 @@ RowDefinition.deregisterFromView = function(rowIds, rowDef) {
14008
13725
  * @return {Object}
14009
13726
  */
14010
13727
  RowDefinition.prototype._getChildStaticRowData = function(ric) {
14011
- if(!this._staticValues) {
14012
- return null;
13728
+ if(this._staticValues) {
13729
+ let childValues = this._staticValues[RowDefinition._childDataField];
13730
+ if(childValues) {
13731
+ return childValues[ric] || null;
13732
+ }
14013
13733
  }
13734
+ return null;
13735
+ };
14014
13736
 
14015
- let childValues = this._staticValues[RowDefinition._childDataField];
14016
- if(!childValues) {
14017
- return null;
13737
+ /** @public
13738
+ * @ignore
13739
+ * @param {string} ric
13740
+ * @return {RowDefinition}
13741
+ */
13742
+ RowDefinition.prototype.getConstituent = function(ric) {
13743
+ if(this._children && ric) {
13744
+ for(let i = this._children.length; --i >= 0;) {
13745
+ if(this._children[i]._ric === ric) {
13746
+ return this._children[i];
13747
+ }
13748
+ }
14018
13749
  }
13750
+ return null;
13751
+ };
14019
13752
 
14020
- return childValues[ric] || null;
13753
+ /** Check whether the given ric can be a constituent of this row definition. WARNING: permId is not handled by this method
13754
+ * @public
13755
+ * @ignore
13756
+ * @param {string} ric
13757
+ * @return {boolean} Returns true if the given ric can be its constituent
13758
+ */
13759
+ RowDefinition.prototype.verifyConstituent = function(ric) {
13760
+ if(this._isChain && ric) { // A constituent must have a valid ric
13761
+ if(this._ric !== ric) { // A constituent cannot have the same ric as its parent
13762
+ if(this._ric !== ("0#" + ric)) { // Real-time service may return ric without 0#
13763
+ return this._ric !== ("/" + ric); // Real-time service may return ric with slash (delayed ric)
13764
+ }
13765
+ }
13766
+ }
13767
+ return false;
14021
13768
  };
14022
- /** @public
13769
+ /** verifyConstituent should be called before calling this method
13770
+ * @public
14023
13771
  * @ignore
14024
13772
  * @param {string} ric
14025
13773
  * @return {RowDefinition} Return newly created child definition, if success
14026
13774
  */
14027
13775
  RowDefinition.prototype.addConstituent = function(ric) {
14028
- if(!ric || this._ric === ric) { // Parent cannot have a child with no name or the same name as itself
14029
- return null;
14030
- }
14031
13776
  if(!(this._rowId && this._subId && this._isChain)) { // Chain must be alive (has not been disposed). Chain must be subscribed as chain
14032
13777
  return null;
14033
13778
  }
14034
13779
 
14035
- let childDef = null;
14036
- if(this._children) {
14037
- for(let i = this._children.length; --i >= 0;) {
14038
- if(this._children[i]._ric === ric) {
14039
- childDef = this._children[i]; // Constituent has already been added
14040
- break;
14041
- }
14042
- }
14043
- } else {
13780
+ if(!this._children) {
14044
13781
  this._children = [];
14045
13782
  }
14046
13783
 
14047
- let newChild = !childDef;
14048
- if(newChild) {
14049
- let rowOptions = {
14050
- "asConstituent": true,
14051
- "dataId": this._subId + ric,
14052
- "ric": ric,
14053
- "parent": this
14054
- };
14055
-
14056
- let staticData = this._getChildStaticRowData(ric);
14057
- if(staticData) {
14058
- rowOptions["values"] = staticData;
14059
- }
14060
-
14061
- childDef = new RowDefinition(rowOptions);
14062
- }
13784
+ let rowOptions = {
13785
+ "asConstituent": true,
13786
+ "ric": ric,
13787
+ "parent": this
13788
+ };
14063
13789
 
14064
- if(this._view) {
14065
- let rowId = this.getRowId();
14066
- // WARNING: insert position, we prioritize using CHILD_ORDER (From server) in dc first. If it does not exist, the last row of the segment will be pushed
14067
- let childOrder = childDef.getData("CHILD_ORDER");
14068
- let dt = this._view.getDataSource();
14069
-
14070
- let parentIndex = dt.getRowIndex(rowId);
14071
- let position = parentIndex + this.getChildCount(); // push the last position
14072
- if(childOrder != null) {
14073
- // Warning: We need to carry a value of 1 because the CHILD_ORDER starts with 0, and it will be added to the parentIndex. In case the parent rowIndex is not included.
14074
- position = parentIndex + childOrder + 1; // insert between segment
14075
- } // else {} it will be push in the last row of segment
14076
- childDef.registerToView(this._view, dt.getRowId(position));
14077
- // TODO: Handle nested children
14078
- this._view.addSegmentChild(rowId, childDef.getRowId(), childDef.getDataId());
13790
+ let staticData = this._getChildStaticRowData(ric); // TODO: Remove the child's static data from parent
13791
+ if(staticData) {
13792
+ rowOptions["values"] = staticData;
14079
13793
  }
14080
13794
 
14081
- return newChild ? childDef : null;
13795
+ return new RowDefinition(rowOptions); // childDef is added to this._children in the constructor
14082
13796
  };
14083
13797
 
14084
13798
  /** Used to convert autogenerated row to regular real-time row
@@ -14086,25 +13800,18 @@ RowDefinition.prototype.addConstituent = function(ric) {
14086
13800
  * @ignore
14087
13801
  */
14088
13802
  RowDefinition.prototype.toRealTimeRow = function() {
14089
- if(!this._ric) { // Empty row
14090
- return;
14091
- }
14092
- if(this.isRowHeader() || !this._parent) {
14093
- return; // If the row is already a normal row or row header, it cannot be converted
13803
+ if(!this.isConstituent()) {
13804
+ return; // Only a constituent can be converted to a real-time row
14094
13805
  }
14095
13806
 
13807
+ let subs = this._parent._subs;
14096
13808
  this._realTime = true;
14097
- this._dc.setRowData(this._dataId, null); // Remove existing data. WARNING: Trigger data update immediately
14098
- this._dataId = this._rowId + this._ric; // JET/RTK will generate data id to be rowId (given from this rowDef) + ric;
14099
-
14100
13809
  this._autoGenerated = false;
14101
13810
  this._parent = null;
14102
13811
  this._depthLevel = 0;
14103
13812
 
14104
- this.subscribeForUpdates();
14105
- if(this._staticValues) { // Add static value to the new allocated row
14106
- this.setRowData(this._staticValues);
14107
- }
13813
+ this.resetRowData(); // WARNING: existing real-time data is lost after this line
13814
+ this.subscribeForUpdates(subs); // Static data remains intact
14108
13815
  };
14109
13816
 
14110
13817
  /** @public
@@ -14114,11 +13821,7 @@ RowDefinition.prototype.unlinkChain = function() {
14114
13821
  return;
14115
13822
  }
14116
13823
 
14117
- let staticData = this._cloneStaticRowData();
14118
- this.unsubscribeForUpdates();
14119
-
14120
- // Restore static data
14121
- this.setStaticRowData(staticData);
13824
+ this.unsubscribeForUpdates(); // Static data remains intact
14122
13825
 
14123
13826
  let view = this._view;
14124
13827
  if(view) {
@@ -14233,6 +13936,22 @@ RowDefinition.prototype.getChildCount = function() {
14233
13936
  return (this._children) ? this._children.length : 0;
14234
13937
  };
14235
13938
  /** @public
13939
+ * @return {number}
13940
+ */
13941
+ RowDefinition.prototype.countChildInView = function() {
13942
+ if(this._children) {
13943
+ let viewCount = 0;
13944
+ let childCount = this._children.length;
13945
+ for(let i = 0; i < childCount; ++i) {
13946
+ if(this._children[i]._view) {
13947
+ ++viewCount;
13948
+ }
13949
+ }
13950
+ return viewCount;
13951
+ }
13952
+ return 0;
13953
+ };
13954
+ /** @public
14236
13955
  * @return {RowDefinition}
14237
13956
  */
14238
13957
  RowDefinition.prototype.getParent = function() {
@@ -24196,7 +23915,8 @@ HScrollbar.prototype.setScrollContent = function (grid, sections, startColIndex,
24196
23915
  column = /** @type{Column} */(section.getColumn(c));
24197
23916
  column.setScrollState(paneElem, null, false);
24198
23917
  }
24199
- pane.setParent(section.getColumnHost());
23918
+ let scrollHost = section.getColumnHost();
23919
+ pane.setParent(scrollHost);
24200
23920
  let columns = [];
24201
23921
  let content = [];
24202
23922
  for (c = startColIndex; c < endColIndex; ++c) {
@@ -24213,9 +23933,11 @@ HScrollbar.prototype.setScrollContent = function (grid, sections, startColIndex,
24213
23933
 
24214
23934
  let rs = section.getReservedSpace();
24215
23935
  if(rs) {
24216
- if(!this._pinnedRightColumnCount) {
23936
+ if(this.isActive() && !this._pinnedRightColumnCount) {
24217
23937
  paneSlider.addContent(rs);
24218
23938
  content.push(rs);
23939
+ } else {
23940
+ scrollHost.appendChild(rs);
24219
23941
  }
24220
23942
  section._updateRightSpaceStyle();
24221
23943
  }
@@ -36572,7 +36294,7 @@ Core.prototype._hasPendingRowChange = false;
36572
36294
  * @return {string}
36573
36295
  */
36574
36296
  Core.getVersion = function () {
36575
- return "5.1.121";
36297
+ return "5.1.125";
36576
36298
  };
36577
36299
  /** {@link ElementWrapper#dispose}
36578
36300
  * @override
@@ -39638,37 +39360,37 @@ Core.prototype.getYScrollVal = function (sectionRef, rowIndex, topOfView) {
39638
39360
  section = this.getSection(sectionRef);
39639
39361
  }
39640
39362
 
39363
+ let rowIndexOffset = (section) ? section.getRowOffset() : this._sectionStarts[this._startVScrollbarIndex];
39364
+ let heightOffset = this._layoutY.getLaneStart(this._startVScrollbarIndex);
39365
+
39641
39366
  let rowCount = this._layoutY.getLaneCount();
39642
39367
  if (rowIndex <= 0) { rowIndex = 0; }
39643
39368
  else if (rowIndex >= rowCount) { rowIndex = rowCount - 1; }
39644
39369
 
39370
+ if (topOfView) {
39371
+ return this._layoutY.getLaneStart(rowIndex + rowIndexOffset) - heightOffset;
39372
+ }
39373
+
39374
+ let bufferSize = 2; // for more appealing space
39645
39375
  let viewInfo = this.getVerticalViewInfo();
39646
39376
  let firstFullRow = viewInfo.firstFullRow; // TODO: Make it work in zooming mode
39647
-
39648
- let scrollIndex = -1;
39649
- if (topOfView) {
39650
- scrollIndex = rowIndex;
39651
- } else {
39652
- if(rowIndex < firstFullRow) { // Scroll up
39653
- scrollIndex = rowIndex - 3; // Have some spaces at the top for more appealing visual
39654
- if(scrollIndex < 0) {
39655
- scrollIndex = 0;
39656
- }
39657
- } else { // Scroll down
39658
- let lastFullRow = viewInfo.lastFullRow;
39659
- if (rowIndex > lastFullRow) {
39660
- let viewIndexSize = lastFullRow - firstFullRow;
39661
- scrollIndex = rowIndex - viewIndexSize + 3;
39662
- if(scrollIndex < 0) {
39663
- scrollIndex = 0;
39664
- }
39665
- }
39377
+ if(rowIndex < firstFullRow) { // Scroll up, as the target row is outside of view
39378
+ let targetIndex = rowIndex - bufferSize; // Have some spaces at the top for more appealing visual
39379
+ if(targetIndex < 0) {
39380
+ targetIndex = 0;
39666
39381
  }
39382
+
39383
+ return this._layoutY.getLaneStart(targetIndex + rowIndexOffset) - heightOffset;
39667
39384
  }
39668
39385
 
39669
- let rowIndexOffset = (section) ? section.getRowOffset() : this._sectionStarts[this._startVScrollbarIndex];
39670
- let heightOffset = this._layoutY.getLaneStart(this._startVScrollbarIndex);
39671
- return (scrollIndex >= 0) ? (this._layoutY.getLaneStart(scrollIndex + rowIndexOffset) - heightOffset) : null;
39386
+ let lastFullRow = viewInfo.lastFullRow;
39387
+ if (rowIndex > lastFullRow) { // Scroll down, as the target row is outside of view
39388
+ let targetScroll = this._layoutY.getLaneStart(rowIndex + rowIndexOffset + bufferSize + 1);
39389
+
39390
+ return targetScroll - viewInfo.viewHeight - heightOffset;
39391
+ }
39392
+
39393
+ return null;
39672
39394
  };
39673
39395
  /** Scroll up or down to make specified row visible in the view
39674
39396
  * @public
@@ -39693,7 +39415,12 @@ Core.prototype.getVerticalViewInfo = function() {
39693
39415
  let viewBottom = viewTop + viewHeight;
39694
39416
 
39695
39417
  let topRowIndex = this._layoutY.hitTest(viewTop) - rowIndexOffset;
39696
- let bottomRowIndex = this._layoutY.hitTest(viewBottom - 0.1) - rowIndexOffset;
39418
+ let bottomRowIndex = this._layoutY.hitTest(viewBottom - 0.1);
39419
+ if(bottomRowIndex < 0) { // view is larger than existing row count
39420
+ bottomRowIndex = this._layoutY.getLaneCount() - 1;
39421
+ }
39422
+ bottomRowIndex -= rowIndexOffset;
39423
+
39697
39424
  let laneTop = this._layoutY.getLaneStart(topRowIndex + rowIndexOffset);
39698
39425
  let laneBottom = this._layoutY.getLaneEnd(bottomRowIndex + rowIndexOffset);
39699
39426
 
@@ -39701,7 +39428,10 @@ Core.prototype.getVerticalViewInfo = function() {
39701
39428
  topRowIndex: topRowIndex,
39702
39429
  firstFullRow: (laneTop < viewTop) ? topRowIndex + 1 : topRowIndex,
39703
39430
  lastFullRow: (laneBottom > viewBottom) ? bottomRowIndex - 1 : bottomRowIndex,
39704
- bottomRowIndex: bottomRowIndex
39431
+ bottomRowIndex: bottomRowIndex,
39432
+ viewHeight: viewHeight,
39433
+ viewTop: viewTop,
39434
+ viewBottom: viewBottom
39705
39435
  };
39706
39436
  };
39707
39437
  /** @public
@@ -45049,12 +44779,6 @@ SortableTitlePlugin._proto = SortableTitlePlugin.prototype;
45049
44779
  * @description Fired only when a row will be removed through Grid's API and before occurring of the actual removal
45050
44780
  */
45051
44781
 
45052
- /** @type {string}
45053
- * @private
45054
- * @const
45055
- */
45056
- const SUB_ID = "SUB_ID";
45057
-
45058
44782
  /** @private
45059
44783
  * @param {RowDefinition} rowDef
45060
44784
  * @return {Object}
@@ -45189,10 +44913,10 @@ let Grid = function(placeholder, config) {
45189
44913
 
45190
44914
  t._onDataChanged = t._onDataChanged.bind(t);
45191
44915
  t._onQuote2PostUpdate = t._onQuote2PostUpdate.bind(t);
44916
+ t._onQ2DataChanged = t._onQ2DataChanged.bind(t);
45192
44917
  t._onDataComposed = t._onDataComposed.bind(t);
45193
44918
  t._onSubSegmentChanged = t._onSubSegmentChanged.bind(t);
45194
44919
  t._recalculateFormulas = t._recalculateFormulas.bind(t);
45195
- t._updateStreamingData = t._updateStreamingData.bind(t);
45196
44920
  t.updateColumnTitle = t.updateColumnTitle.bind(t);
45197
44921
  t._populateTimeSeriesChildren = t._populateTimeSeriesChildren.bind(t);
45198
44922
 
@@ -45204,7 +44928,7 @@ let Grid = function(placeholder, config) {
45204
44928
  t._updateRowData = t._updateRowData.bind(t);
45205
44929
  t._onFormulaDataChanged = t._onFormulaDataChanged.bind(t);
45206
44930
  t._onFormulaDataRequired = t._onFormulaDataRequired.bind(t);
45207
- t._addMemberOfChain = t._addMemberOfChain.bind(t);
44931
+ t._registerConstituents = t._registerConstituents.bind(t);
45208
44932
  t._onColumnAdded = t._onColumnAdded.bind(t);
45209
44933
  t._onRowExpansionBinding = t._onRowExpansionBinding.bind(t);
45210
44934
  t._onColumnHeaderBinding = t._onColumnHeaderBinding.bind(t);
@@ -45219,9 +44943,9 @@ let Grid = function(placeholder, config) {
45219
44943
  t._onVScroll = t._onVScroll.bind(t);
45220
44944
  t._selfScrollToRow = t._selfScrollToRow.bind(t);
45221
44945
 
45222
- t._streamingConflator = new Conflator(50, t._updateStreamingData);
44946
+ t._dcConflator = new Conflator(50, t._onDataChanged);
45223
44947
  t._formulaConflator = new Conflator(300, t._onFormulaDataChanged);
45224
- t._chainConflator = new Conflator(100, t._addMemberOfChain);
44948
+ t._chainConflator = new Conflator(100, t._registerConstituents);
45225
44949
  t._columnTitleConflator = new Conflator(0, t.updateColumnTitle);
45226
44950
  t._timeSeriesChildConflator = new Conflator(0, t._populateTimeSeriesChildren);
45227
44951
 
@@ -45358,7 +45082,7 @@ Grid.prototype._sharedDataSource = false;
45358
45082
  */
45359
45083
  Grid.prototype._sharedSorter = false;
45360
45084
 
45361
- /** JET.Quotes2 Subscription
45085
+ /** JET/RTK's Quotes2 subscription object
45362
45086
  * @type {Object}
45363
45087
  * @private
45364
45088
  */
@@ -45376,7 +45100,7 @@ Grid.prototype._columnSorter = null;
45376
45100
  /** @private
45377
45101
  * @type {Conflator}
45378
45102
  */
45379
- Grid.prototype._streamingConflator = null;
45103
+ Grid.prototype._dcConflator = null;
45380
45104
  /** @private
45381
45105
  * @type {SnapshotFiller}
45382
45106
  */
@@ -45399,10 +45123,6 @@ Grid.prototype._fnEngine = null;
45399
45123
  */
45400
45124
  Grid.prototype._formulaConflator = null;
45401
45125
 
45402
- /** @private
45403
- * @type {Object.<string, Object>}
45404
- */
45405
- Grid.prototype._chainMembers = null;
45406
45126
  /** @private
45407
45127
  * @type {Conflator}
45408
45128
  */
@@ -45511,7 +45231,15 @@ Grid.prototype.dispose = function() {
45511
45231
  this._grid.dispose();
45512
45232
  this._connector.reset();
45513
45233
 
45514
- if(!this._sharedDataSource) { // make sure that it is the final grid, and that it will be dispose data
45234
+ if(!this._sharedDataSource) { // Make sure that this is the final grid, and its data is disposed
45235
+ if(this._subs) {
45236
+ this._subs.removeEventListener("postUpdate", this._onQuote2PostUpdate);
45237
+ this._subs.removeEventListener("dataChanged", this._onQ2DataChanged);
45238
+ this._subs["dispose"]();
45239
+ }
45240
+ if(this._dc) {
45241
+ this._dc.dispose();
45242
+ }
45515
45243
  if(this._dt) {
45516
45244
  this._dt.dispose();
45517
45245
  }
@@ -45519,12 +45247,7 @@ Grid.prototype.dispose = function() {
45519
45247
  this._dv.dispose();
45520
45248
  }
45521
45249
  }
45522
- this._mainGrid = this._dt = this._dv = null;
45523
-
45524
- if(this._subs) {
45525
- this._subs["dispose"]();
45526
- this._subs = null;
45527
- }
45250
+ this._mainGrid = this._dc = this._dt = this._dv = this._subs = null;
45528
45251
 
45529
45252
  if(this._focusingArgs) {
45530
45253
  _clearTimeout(this._focusingArgs.id);
@@ -45553,7 +45276,11 @@ Grid.prototype.listen = Grid.prototype.addEventListener;
45553
45276
  /** @public
45554
45277
  */
45555
45278
  Grid.prototype.initSubscription = function() {
45556
- if(!this._dc || this._dc.getSubscriptions()) { // Subscription is already initialized
45279
+ if(this._subs) { // Subscription is already initialized
45280
+ return;
45281
+ }
45282
+ if(this._sharedDataSource) {
45283
+ this._subs = this._mainGrid._subs;
45557
45284
  return;
45558
45285
  }
45559
45286
 
@@ -45566,6 +45293,9 @@ Grid.prototype.initSubscription = function() {
45566
45293
  }
45567
45294
  if(q) {
45568
45295
  s = q["create"]();
45296
+ if(this._RTK && this._RTK.prefetchWorkaround) { // The workaround for RTK Quotes has a bug concerning the removal of the last row; it isn't removed.
45297
+ s.addRic("DUMMY.WORKAROUND", "DUMMY.WORKAROUND");
45298
+ }
45569
45299
  }
45570
45300
  if(!s) {
45571
45301
  return;
@@ -45576,8 +45306,8 @@ Grid.prototype.initSubscription = function() {
45576
45306
 
45577
45307
  this._subs = s;
45578
45308
  this._subs["start"]();
45579
- this._dc.setSubscriptions(s);
45580
45309
  this._subs.addEventListener("postUpdate", this._onQuote2PostUpdate);
45310
+ this._subs.addEventListener("dataChanged", this._onQ2DataChanged);
45581
45311
 
45582
45312
  // TODO: Subscriptions should be registered per row.
45583
45313
  // However, chain subscription cannot be integrated with DataConnector in this current implementation.
@@ -45586,7 +45316,7 @@ Grid.prototype.initSubscription = function() {
45586
45316
  for(let i = 0; i < len; ++i) {
45587
45317
  let rowDef = rowDefs[i];
45588
45318
  if(rowDef) {
45589
- rowDef.subscribeForUpdates();
45319
+ rowDef.subscribeForUpdates(s);
45590
45320
  }
45591
45321
  }
45592
45322
  };
@@ -47194,29 +46924,31 @@ Grid.prototype._initDuplicateRicData = function(rowDef) {
47194
46924
  };
47195
46925
 
47196
46926
  /** @private
47197
- * @param {Object} rowDef
47198
- * @param {Array<Object>} children
46927
+ * @param {Object} newRowDef
47199
46928
  */
47200
- Grid.prototype._cloneChain = function(rowDef) {
47201
- let rowDefs = this._connector.getRowDefByRic(rowDef.getSymbol());
46929
+ Grid.prototype._cloneChain = function(newRowDef) {
46930
+ let rowDefs = this._connector.getRowDefByRic(newRowDef.getSymbol());
47202
46931
  let firstRowDef = rowDefs ? rowDefs[0] : null;
47203
46932
  let constituents = firstRowDef ? firstRowDef.getChildren() : null;
47204
-
47205
- if(!constituents) {
47206
- return;
47207
- }
47208
- let count = constituents.length;
47209
- if(count < 0 ) {
46933
+ let count = constituents ? constituents.length : 0;
46934
+ if(count < 0) {
47210
46935
  return;
47211
46936
  }
47212
46937
 
47213
- let subId = rowDef.getData(SUB_ID);
46938
+ let subId = newRowDef.getSubId();
46939
+ if(!subId) {
46940
+ return; // A chain without subscription cannot have constituents
46941
+ }
46942
+ let evtArg = {
46943
+ "subId": subId
46944
+ };
47214
46945
  for (let i = 0; i < count; i++) {
47215
- let childRowDef = constituents[i];
47216
- let rowData = childRowDef.cloneRowData();
47217
- rowData["SUB_ID"] = subId;
47218
- let rid = subId + rowData["RIC"];
47219
- this._dc.setRowData(rid, rowData);
46946
+ let childRowDef = constituents[i]; // TODO: the constituents should be sorted by CHILD_ORDER first
46947
+ evtArg["ric"] = childRowDef.getRic();
46948
+ evtArg["values"] = childRowDef.cloneRowData();
46949
+ evtArg["values"]["SUB_ID"] = subId; // Imitate real-time service responses
46950
+
46951
+ this._onQ2DataChanged(evtArg); // WARNING: evtArg is shared across multiple calls
47220
46952
  }
47221
46953
  };
47222
46954
  /** @public
@@ -47242,7 +46974,7 @@ Grid.prototype.insertRow = function(rowOption, rowRef) {
47242
46974
  }
47243
46975
  }
47244
46976
  let rowDef = new RowDefinition(rowOption);
47245
- rowDef.setDataSource(this._dc); // This could also subscribe chain index/ric to JET/RTK
46977
+ rowDef.setDataSource(this._dc, this._subs); // This could also subscribe chain index/ric to JET/RTK
47246
46978
  this._initDuplicateRicData(rowDef);
47247
46979
 
47248
46980
  rowDef.registerToView(this._dv, this._getRowId(rowRef));
@@ -47554,17 +47286,16 @@ Grid.prototype.removeAllRows = function() {
47554
47286
  if(!this._dt.getRowCount()) {
47555
47287
  return;
47556
47288
  }
47289
+ // Data source is not shared at this point
47557
47290
  let rowDefs = this._getAllRowDefinitions();
47558
47291
 
47559
- if(!this._sharedDataSource) {
47560
- this._dc.clearAllData();
47561
- this._dt.clearAllData();
47562
- this._clearDataUpdates();
47563
- }
47292
+ this._dc.clearAllData();
47293
+ this._dt.clearAllData();
47294
+ this._clearDataUpdates();
47564
47295
 
47565
- rowDefs.forEach(RowDefinition.dispose);
47296
+ rowDefs.forEach(RowDefinition.dispose); // Each individual subscription is unsubscribed along with disposed rowDef
47566
47297
 
47567
- this._streamingConflator.reset();
47298
+ this._dcConflator.reset();
47568
47299
  this._formulaConflator.reset();
47569
47300
  this._chainConflator.reset();
47570
47301
  this._connector.removeAllRics();
@@ -48461,94 +48192,127 @@ Grid.prototype._onQuote2PostUpdate = function (e) {
48461
48192
  }
48462
48193
  };
48463
48194
 
48464
- /** @private
48465
- * @param {!Object} e
48466
- */
48467
- Grid.prototype._onDataChanged = function(e) {
48468
- let rowData = e["rowData"]; // Use rowData to retrieve corresponding subscription object
48469
- if (!rowData || this._unlinking) {
48470
- return; // This must be a global change
48195
+ /**
48196
+ * @private
48197
+ * @param {Object} e
48198
+ */
48199
+ Grid.prototype._onQ2DataChanged = function (e) {
48200
+ let subId = e["subId"];
48201
+ let rowDef = this._getRowDefinitionById(subId);
48202
+ if(!rowDef) {
48203
+ return; // WARNING: This should not be happened because row has been removed but the data is still received
48471
48204
  }
48472
- let rowDef = rowData[ROW_DEF];
48473
48205
 
48474
- if(rowDef) {
48475
- let rowId = rowDef.getRowId();
48476
- if(rowId) {
48477
- // e["rid"] could be from JET/RTK (rowId + ric) or static data update (rowId)
48478
- let curRowData = this._dc.getRowData(e["rid"]);
48479
- if (curRowData) {
48480
- if(rowDef.addUpdate(e)) { // This is the only place that update array can grow. It is used for blinking data.
48481
- this._dt._hasNewUpdates = true; // Mark data table for cleaning it up later
48206
+ let values = e["values"];
48207
+ if (values) {
48208
+ let ric = e["ric"];
48209
+ if(rowDef.verifyConstituent(ric)) {
48210
+ let parentDef = rowDef;
48211
+ let childDef = parentDef.getConstituent(ric);
48212
+ if(childDef) { // The constituent will share the same sub id as its parent
48213
+ rowDef = childDef;
48214
+ } else {
48215
+ rowDef = childDef = parentDef.addConstituent(ric);
48216
+ if(!childDef) {
48217
+ return; // Parent chain is not alive
48482
48218
  }
48483
- this._updateStreamingData();
48484
- } else if(rowDef.isAutoGenerated()) { // Subscription and its parent has been removed by Real-time provider
48485
- rowDef.setParent(null); // Manually remove child reference from its parent
48486
- this._removeRow(rowDef);
48219
+ this._connector.addRic(childDef); // TODO: JET/RTK should not re-subscribe this
48220
+ this._registerConstituents(childDef);
48487
48221
  }
48488
48222
  }
48489
- return;
48490
- }
48491
48223
 
48492
- // The new data update has no row definition, meaning that we have found a new constituent from a chain.
48493
- let subId = rowData[SUB_ID]; // The constituent will share the same sub id as its parent
48494
- if(subId) {
48495
- let parentDef = this._getRowDefinitionById(subId);
48496
- if(parentDef && parentDef.isChain() && parentDef.getRic() !== rowData["RIC"]) { // TODO: Check for delayed ric
48497
- if(!this._chainMembers) {
48498
- this._chainMembers = {};
48499
- }
48500
- if(!this._chainMembers[e["rid"]]) { // Prevent duplication
48501
- this._chainMembers[e["rid"]] = rowData;
48502
- this._addMemberOfChain(rowData);
48503
- }
48504
- }
48224
+ rowDef.setRowData(values); // Trigger data changes
48225
+ } else if(rowDef.isConstituent()) { // Subscription and its parent has been removed by Real-time provider
48226
+ rowDef.setParent(null); // Manually remove child reference from its parent
48227
+ this._removeRow(rowDef);
48505
48228
  }
48506
48229
  };
48230
+
48507
48231
  /** @private
48508
- * @param {!Object} rowData
48232
+ * @param {RowDefinition} rowDef
48509
48233
  */
48510
- Grid.prototype._addMemberOfChain = function(rowData) {
48511
- if(this._chainConflator.conflate(rowData)) {
48234
+ Grid.prototype._registerConstituents = function(rowDef) {
48235
+ if(this._chainConflator.conflate(rowDef)) {
48236
+ return;
48237
+ }
48238
+ let view = this._dv;
48239
+ let dt = view ? view.getDataSource() : null;
48240
+ if(!dt) {
48512
48241
  return;
48513
48242
  }
48514
48243
 
48515
- let rows = this._chainConflator.popAllData(); // This must have no duplication
48516
- let len = rows ? rows.length : 0;
48244
+ let childDefs = this._chainConflator.popAllData(); // This must have no duplication
48245
+ let childCount = childDefs ? childDefs.length : 0;
48246
+
48247
+ // Validate row definition and collect its info
48517
48248
  let i;
48249
+ let validDefs = [];
48250
+ let maxCountMap = {};
48251
+ for(i = 0; i < childCount; ++i) {
48252
+ let childDef = childDefs[i];
48253
+ let parentDef = childDef.getParent();
48254
+ if(!parentDef) {
48255
+ break; // A constituent without parent cannot be added to the view
48256
+ }
48257
+ let parentRowId = parentDef.getRowId();
48258
+ let maxCount = maxCountMap[parentRowId];
48259
+ if(maxCount == null) {
48260
+ maxCount = maxCountMap[parentRowId] = parentDef.countChildInView();
48261
+ }
48262
+ validDefs.push(childDef);
48263
+ }
48264
+
48265
+ childCount = validDefs.length;
48266
+ if(!childCount) {
48267
+ return;
48268
+ }
48518
48269
 
48519
48270
  let prevState = false;
48520
- if(len > 1) {
48271
+ if(childCount > 1) {
48521
48272
  prevState = this._dt.freeze(); // Avoid sorting for each insertion
48522
48273
  }
48523
- let childDefs = [];
48524
- for(i = 0; i < len; ++i) {
48525
- rowData = /** @type{!Object} */(rows[i]);
48526
- let subId = rowData[SUB_ID];
48527
- let parentDef = this._getRowDefinitionById(subId);
48528
- if(parentDef) {
48529
- let childDef = parentDef.addConstituent(/** @type{string} */(rowData["RIC"]), this._dt);
48530
- if(childDef) {
48531
- childDefs.push(childDef);
48532
- } // else { // childDef has already been added
48533
- }
48534
- }
48535
- this._chainMembers = null; // Clear all waiting chain members
48536
48274
 
48537
- let childCount = childDefs.length;
48538
- if(childCount) {
48539
- for(i = childCount; --i >= 0;) {
48540
- this._connector.addRic(childDefs[i]); // TODO: JET/RTK should not re-subscribe this
48275
+ for(i = 0; i < childCount; ++i) {
48276
+ let childDef = validDefs[i];
48277
+ let parentDef = childDef.getParent();
48278
+ let parentRowId = parentDef.getRowId();
48279
+ let maxCount = maxCountMap[parentRowId];
48280
+
48281
+ // TODO: Handle nested children
48282
+ view.addSegmentChild(parentRowId, childDef.getRowId());
48283
+
48284
+ // Added order and child order can be different
48285
+ // CHILD_ORDER value from real-time service indicates the order of constituents.
48286
+ let destIndex = dt.getRowIndex(parentRowId) + 1; // WARNING: Not checking for negative index
48287
+ let childOrder = childDef.getData("CHILD_ORDER"); // CHILD_ORDER starts from 0
48288
+ if(childOrder != null && childOrder < maxCount) {
48289
+ destIndex += childOrder;
48290
+ } else {
48291
+ destIndex += maxCount;
48541
48292
  }
48293
+ let destRowId = dt.getRowId(destIndex);
48294
+ childDef.registerToView(view, destRowId);
48295
+ maxCountMap[parentRowId] = maxCount + 1; // Since new child has been added to the view, maxCount has to be updated
48542
48296
  }
48543
- if(len > 1) {
48297
+ if(childCount > 1) {
48544
48298
  this._dt.freeze(prevState);
48545
48299
  }
48546
48300
  };
48547
48301
 
48548
48302
  /** @private
48303
+ * @param {Object} e
48549
48304
  */
48550
- Grid.prototype._updateStreamingData = function() {
48551
- if(this._streamingConflator.conflate()) {
48305
+ Grid.prototype._onDataChanged = function(e) {
48306
+ if(this._dt && e && e["rid"] && e["changes"]) {
48307
+ let rowDef = this._getRowDefinitionById(e["rid"]);
48308
+ if(rowDef) {
48309
+ if(rowDef.addUpdate(e["changes"])) { // This is the only place that update array can grow. It is used for blinking data.
48310
+ this._dt._hasNewUpdates = true; // Mark data table for cleaning it up later
48311
+ }
48312
+ }
48313
+ }
48314
+
48315
+ if(this._dcConflator.conflate()) {
48552
48316
  return;
48553
48317
  }
48554
48318
 
@@ -48849,9 +48613,9 @@ Grid.prototype._onSubSegmentChanged = function(e) {
48849
48613
  // let parentId = segment.getParentId();
48850
48614
  let segmentId = segment.getId();
48851
48615
  rowDef = new RowDefinition({
48852
- "segmentId": segmentId
48616
+ "segmentId": segmentId // WARNING: This could cause row id duplication
48853
48617
  });
48854
- rowDef.setDataSource(this._dc);
48618
+ rowDef.setDataSource(this._dc); // auto generated row does not require a subscription
48855
48619
  rowDef.registerToView(this._dv);
48856
48620
  }
48857
48621
  };
@@ -52886,10 +52650,6 @@ CellPainter.prototype._scopes;
52886
52650
  * @private
52887
52651
  */
52888
52652
  CellPainter.prototype._columnStats = null;
52889
- /** @type {boolean}
52890
- * @private
52891
- */
52892
- CellPainter.prototype._levelColorDisabled = false;
52893
52653
  /** @type {number}
52894
52654
  * @private
52895
52655
  */
@@ -52945,6 +52705,10 @@ CellPainter.supportedStyles = CellPainter.bgStyles.concat(CellPainter.nonBgStyle
52945
52705
  * @public
52946
52706
  */
52947
52707
  CellPainter.themeReady = null;
52708
+ /** @type {Object}
52709
+ * @private
52710
+ */
52711
+ CellPainter._contrastColors = {};
52948
52712
 
52949
52713
  /** Deprecated in favor of ExpressionParser
52950
52714
  * @public
@@ -53538,7 +53302,7 @@ CellPainter.prototype._getStyles = function(rowData, min, max) {
53538
53302
  } else if(ret < 0) {
53539
53303
  curCond["cssClass"] = curCond["downClass"];
53540
53304
  } else {
53541
- curCond["cssClass"] = this._levelColorDisabled ? "" : curCond["levelClass"];
53305
+ curCond["cssClass"] = curCond["levelClass"];
53542
53306
  }
53543
53307
  curCond["cssClass"] = curCond["cssClass"] || "";
53544
53308
  return curCond;
@@ -53739,8 +53503,12 @@ CellPainter._clearBlinkTimer = function(scp, opt_restoreColor) {
53739
53503
  CellPainter.getOppositeColor = function (hexCode) {
53740
53504
  if(typeof hexCode === "string") {
53741
53505
  if(hexCode.charAt(0) === "#") {
53742
- let triplet = hex2Num(hexCode);
53743
- return getContrastColor(triplet);
53506
+ let contrastColor = CellPainter._contrastColors[hexCode];
53507
+ if (!contrastColor) {
53508
+ let triplet = hex2Num(hexCode);
53509
+ contrastColor = CellPainter._contrastColors[hexCode] = getContrastColor(triplet);
53510
+ }
53511
+ return contrastColor;
53744
53512
  }
53745
53513
  } else if(Array.isArray(hexCode)) {
53746
53514
  return getContrastColor(hexCode);
@@ -53834,67 +53602,48 @@ CellPainter.prototype._paintCell = function(cell, rowData, min, max) {
53834
53602
  };
53835
53603
 
53836
53604
  /**
53837
- * @public
53605
+ * @private
53838
53606
  * @param {tr.grid.Cell} cell
53839
- * @param {number} blinkSignal
53840
- * @param {Object} rowData to calculate original style e.g. { PCTCHNG: 0.53, CF_NETCHNG: 0.75 }
53607
+ * @return {Object}
53841
53608
  */
53842
- CellPainter.prototype.blink = function (cell, blinkSignal, rowData) {
53843
- this._blinkCell(cell, rowData, blinkSignal);
53844
- };
53609
+ CellPainter.prototype._prepareScope = function(cell) {
53610
+ let scope = cell["blinking"];
53611
+ if (!scope) {
53612
+ scope = {};
53613
+ scope["cell"] = cell;
53614
+ cell["blinking"] = scope;
53615
+
53616
+ this._scopes.push(scope);
53617
+ }
53845
53618
 
53846
- /**
53847
- * @public
53848
- * @param {tr.grid.Cell} cell
53849
- * @param {number} newValue
53850
- * @param {number} oldValue
53851
- * @param {Object} rowData e.g. { PCTCHNG: 0.53, CF_NETCHNG: 0.75 }
53852
- * @return {boolean}
53853
- */
53854
- CellPainter.prototype.blinkCell = function(cell, newValue, oldValue, rowData) {
53855
53619
  let bc = this._blinkCondition;
53856
- if (!bc) return false;
53620
+ if (scope["blinkId"] !== bc["blinkId"]) {
53621
+ scope["blinkId"] = bc["blinkId"];
53622
+ scope["field"] = bc["field"];
53623
+ let restorer = bc["border"] ? CellPainter._borderRestorer : CellPainter._cellRestorer;
53624
+ scope._restorer = restorer.bind(this, scope);
53625
+ }
53857
53626
 
53858
- let blinkSignal = this._blinkCondition._fn(newValue, oldValue);
53859
- return this._blinkCell(cell, rowData, blinkSignal);
53627
+ return scope;
53860
53628
  };
53861
53629
 
53862
- /** @private
53630
+ /**
53631
+ * @public
53863
53632
  * @param {tr.grid.Cell} cell
53864
- * @param {Object} rowData e.g. { PCTCHNG: 0.53, CF_NETCHNG: 0.75 }
53865
53633
  * @param {number} blinkSignal
53634
+ * @param {Object} rowData to calculate original style e.g. { PCTCHNG: 0.53, CF_NETCHNG: 0.75 }
53866
53635
  * @return {boolean}
53867
53636
  */
53868
- CellPainter.prototype._blinkCell = function(cell, rowData, blinkSignal) {
53637
+ CellPainter.prototype.blink = function (cell, blinkSignal, rowData) {
53869
53638
  if (!cell) return false;
53870
53639
 
53871
- if (this._levelColorDisabled) {
53872
- if(!blinkSignal) { // Disabled level color equivalent to no blinking for blink signal 0
53873
- return false;
53874
- }
53875
- }
53876
-
53877
53640
  let elem = cell.getElement();
53878
53641
  if (!elem) return false; // Cell has been disposed
53879
53642
 
53880
53643
  let bc = this._blinkCondition;
53881
53644
  if (!bc) return false;
53882
53645
 
53883
- let scope = cell["blinking"];
53884
- if (!scope) {
53885
- scope = {};
53886
- scope["cell"] = cell;
53887
- cell["blinking"] = scope;
53888
-
53889
- this._scopes.push(scope);
53890
- }
53891
-
53892
- if (scope["blinkId"] !== bc["blinkId"]) {
53893
- scope["blinkId"] = bc["blinkId"];
53894
- scope["field"] = bc["field"];
53895
- let restorer = bc["border"] ? CellPainter._borderRestorer : CellPainter._cellRestorer;
53896
- scope._restorer = restorer.bind(this, scope);
53897
- }
53646
+ let scope = this._prepareScope(cell);
53898
53647
 
53899
53648
  scope["rowData"] = rowData;
53900
53649
 
@@ -53910,9 +53659,47 @@ CellPainter.prototype._blinkCell = function(cell, rowData, blinkSignal) {
53910
53659
  contrastColor = bc["contrastLevelColor"];
53911
53660
  }
53912
53661
 
53662
+ return this._blink(scope, elem, blinkColor, contrastColor);
53663
+ };
53664
+
53665
+ /** Blink cell with specific color or theme's neutral movement color.
53666
+ * @public
53667
+ * @param {tr.grid.Cell} cell
53668
+ * @param {string|null} blinkColor
53669
+ * @param {Object} rowData to calculate original style e.g. { PCTCHNG: 0.53, CF_NETCHNG: 0.75 }
53670
+ * @return {boolean}
53671
+ */
53672
+ CellPainter.prototype.flash = function(cell, blinkColor, rowData) {
53673
+ if (!cell) return false;
53674
+
53675
+ let elem = cell.getElement();
53676
+ if (!elem) return false; // Cell has been disposed
53677
+
53678
+ if (!this._blinkCondition) return false;
53679
+
53680
+ let scope = this._prepareScope(cell);
53681
+
53682
+ scope["rowData"] = rowData;
53683
+
53684
+ if (typeof blinkColor !== "string") {
53685
+ blinkColor = ElfUtil.themeColors["level"];
53686
+ }
53687
+
53688
+ return this._blink(scope, elem, blinkColor, CellPainter.getOppositeColor(blinkColor));
53689
+ };
53690
+
53691
+ /**
53692
+ * @public
53693
+ * @param {Object} scope
53694
+ * @param {Element} elem
53695
+ * @param {string} blinkColor
53696
+ * @param {string} contrastColor
53697
+ * @return {boolean}
53698
+ */
53699
+ CellPainter.prototype._blink = function (scope, elem, blinkColor, contrastColor) {
53913
53700
  let bgBlinking = true;
53914
- // All conditions are met for blinking
53915
- if (bc["border"]) {
53701
+
53702
+ if (this._blinkCondition["border"]) {
53916
53703
  elem.style.border = "1px solid " + blinkColor;
53917
53704
  bgBlinking = false;
53918
53705
  } else {
@@ -53926,6 +53713,36 @@ CellPainter.prototype._blinkCell = function(cell, rowData, blinkSignal) {
53926
53713
  return bgBlinking;
53927
53714
  };
53928
53715
 
53716
+ /**
53717
+ * @public
53718
+ * @param {tr.grid.Cell} cell
53719
+ * @param {number} newValue
53720
+ * @param {number} oldValue
53721
+ * @param {Object} rowData e.g. { PCTCHNG: 0.53, CF_NETCHNG: 0.75 }
53722
+ * @return {boolean}
53723
+ */
53724
+ CellPainter.prototype.blinkCell = function(cell, newValue, oldValue, rowData) {
53725
+ let bc = this._blinkCondition;
53726
+ if (!bc) return false;
53727
+
53728
+ let blinkSignal = this._blinkCondition._fn(newValue, oldValue);
53729
+ return this.blink(cell, blinkSignal, rowData);
53730
+ };
53731
+
53732
+ /**
53733
+ * @public
53734
+ * @ignore
53735
+ * @param {number} newValue
53736
+ * @param {number} oldValue
53737
+ * @return {number}
53738
+ */
53739
+ CellPainter.prototype.calcBlinkSignal = function(newValue, oldValue) {
53740
+ if (this._blinkCondition) {
53741
+ return this._blinkCondition._fn(newValue, oldValue);
53742
+ }
53743
+ return 0;
53744
+ };
53745
+
53929
53746
  /**
53930
53747
  * @public
53931
53748
  * @param {tr.grid.Cell} cell
@@ -53942,13 +53759,12 @@ CellPainter.prototype.verifyBlinking = function(cell, rowData) {
53942
53759
  }
53943
53760
  }
53944
53761
  };
53945
- /**
53762
+ /** Deprecated, the state has been moved out to support prioritization.
53946
53763
  * @public
53764
+ * @deprecated
53947
53765
  * @param {boolean=} disabled
53948
53766
  */
53949
- CellPainter.prototype.disableLevelColor = function(disabled) {
53950
- this._levelColorDisabled = disabled !== false;
53951
- };
53767
+ CellPainter.prototype.disableLevelColor = function(disabled) {};
53952
53768
  /**
53953
53769
  * @public
53954
53770
  * @param {number} duration