@refinitiv-ui/efx-grid 6.0.119 → 6.0.121

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. package/README.md +1 -1
  2. package/lib/column-dragging/es6/ColumnDragging.js +7 -4
  3. package/lib/core/dist/core.js +104 -10
  4. package/lib/core/dist/core.min.js +1 -1
  5. package/lib/core/es6/data/DataView.js +7 -5
  6. package/lib/core/es6/grid/Core.js +3 -3
  7. package/lib/core/es6/grid/components/Cell.d.ts +2 -0
  8. package/lib/core/es6/grid/components/Cell.js +89 -0
  9. package/lib/core/es6/grid/components/HScrollbar.d.ts +1 -1
  10. package/lib/core/es6/grid/components/HScrollbar.js +5 -2
  11. package/lib/filter-dialog/themes/base-checkbox.less +1 -1
  12. package/lib/filter-dialog/themes/base.less +8 -3
  13. package/lib/filter-dialog/themes/elemental/dark/checkbox-list.js +1 -1
  14. package/lib/filter-dialog/themes/elemental/dark/es5/all-elements.js +2 -2
  15. package/lib/filter-dialog/themes/elemental/dark/filter-dialog.js +1 -1
  16. package/lib/filter-dialog/themes/elemental/light/checkbox-list.js +1 -1
  17. package/lib/filter-dialog/themes/elemental/light/es5/all-elements.js +2 -2
  18. package/lib/filter-dialog/themes/elemental/light/filter-dialog.js +1 -1
  19. package/lib/filter-dialog/themes/halo/dark/checkbox-list.js +1 -1
  20. package/lib/filter-dialog/themes/halo/dark/es5/all-elements.js +2 -2
  21. package/lib/filter-dialog/themes/halo/dark/filter-dialog.js +1 -1
  22. package/lib/filter-dialog/themes/halo/light/checkbox-list.js +1 -1
  23. package/lib/filter-dialog/themes/halo/light/es5/all-elements.js +2 -2
  24. package/lib/filter-dialog/themes/halo/light/filter-dialog.js +1 -1
  25. package/lib/filter-dialog/themes/solar/charcoal/checkbox-list.js +1 -1
  26. package/lib/filter-dialog/themes/solar/charcoal/es5/all-elements.js +2 -2
  27. package/lib/filter-dialog/themes/solar/charcoal/filter-dialog.js +1 -1
  28. package/lib/filter-dialog/themes/solar/pearl/checkbox-list.js +1 -1
  29. package/lib/filter-dialog/themes/solar/pearl/es5/all-elements.js +2 -2
  30. package/lib/filter-dialog/themes/solar/pearl/filter-dialog.js +1 -1
  31. package/lib/grid/index.js +1 -1
  32. package/lib/rt-grid/dist/rt-grid.js +240 -104
  33. package/lib/rt-grid/dist/rt-grid.min.js +1 -1
  34. package/lib/rt-grid/es6/ColumnDefinition.js +7 -0
  35. package/lib/rt-grid/es6/Grid.js +108 -81
  36. package/lib/rt-grid/es6/RowDefinition.d.ts +1 -1
  37. package/lib/rt-grid/es6/RowDefinition.js +28 -17
  38. package/lib/tr-grid-auto-tooltip/es6/AutoTooltip.js +18 -15
  39. package/lib/tr-grid-checkbox/es6/Checkbox.js +4 -0
  40. package/lib/tr-grid-column-grouping/es6/ColumnGrouping.js +6 -1
  41. package/lib/tr-grid-filter-input/es6/FilterInput.js +1 -0
  42. package/lib/tr-grid-row-dragging/es6/RowDragging.d.ts +0 -2
  43. package/lib/tr-grid-row-dragging/es6/RowDragging.js +82 -77
  44. package/lib/tr-grid-row-selection/es6/RowSelection.js +155 -35
  45. package/lib/types/es6/Core/grid/components/Cell.d.ts +2 -0
  46. package/lib/types/es6/Core/grid/components/HScrollbar.d.ts +1 -1
  47. package/lib/types/es6/RealtimeGrid/RowDefinition.d.ts +1 -1
  48. package/lib/types/es6/RowDragging.d.ts +0 -2
  49. package/lib/utils/index.d.ts +1 -1
  50. package/lib/utils/index.js +1 -1
  51. package/lib/versions.json +8 -8
  52. package/package.json +1 -1
@@ -12941,7 +12941,7 @@ DataTable._proto = DataTable.prototype;
12941
12941
  * @property {boolean=} hidden=true When this row is hidden
12942
12942
  * @property {boolean=} realTime=true Realtime row, able to request for JET/RTK
12943
12943
  * @property {Object=} info=null For storing any additional information to the row
12944
- * @property {string=} rowId Row identifier used for referencing the row
12944
+ * @property {string=} rowId Row identifier used for referencing the row. The value cannot be in "_x_" format.
12945
12945
  */
12946
12946
 
12947
12947
  /** @typedef {Object} RowDefinition~RowTypes
@@ -12972,6 +12972,12 @@ const ROW_TYPES = {
12972
12972
  GROUP_MEMBER: "GROUP_MEMBER"
12973
12973
  };
12974
12974
 
12975
+ /** @type {RegExp}
12976
+ * @private
12977
+ * @const
12978
+ */
12979
+ const ROW_ID_PATTERN = /^_[^_]+_$/;
12980
+
12975
12981
  /** @constructor
12976
12982
  * @param {RowDefinition~Options=} rowOptions
12977
12983
  */
@@ -13160,8 +13166,12 @@ RowDefinition.prototype.initialize = function(rowOptions) {
13160
13166
  if(!this._autoGenerated) {
13161
13167
  let userRowId = rowOptions["rowId"];
13162
13168
  if(userRowId && typeof userRowId === "string") {
13163
- this._rowId = this._dataId = userRowId;
13164
- this._userId = true;
13169
+ if(userRowId.match(ROW_ID_PATTERN)) {
13170
+ console.warn("Please change the rowId format to avoid duplicated rows' id causing unexpected behavior.");
13171
+ } else {
13172
+ this._rowId = this._dataId = userRowId;
13173
+ this._userId = true;
13174
+ }
13165
13175
  }
13166
13176
  }
13167
13177
 
@@ -13915,14 +13925,20 @@ RowDefinition.prototype.resetUpdates = function() {
13915
13925
 
13916
13926
  /** @public
13917
13927
  * @param {DataView} view
13918
- * @param {string=} rowId
13928
+ * @param {string=} destRowId Destination position where the row will be placed BEFORE the specified position.
13919
13929
  */
13920
- RowDefinition.prototype.registerToView = function(view, rowId) {
13930
+ RowDefinition.prototype.registerToView = function(view, destRowId) {
13921
13931
  if(!view || this._view === view) {
13922
13932
  return; // Already in the view
13923
13933
  }
13924
13934
  this._view = view;
13925
13935
 
13936
+ let rowId = this.getRowId();
13937
+ if(view.getRowData(rowId)) {
13938
+ console.warn("Duplicated rows' id.");
13939
+ return;
13940
+ }
13941
+
13926
13942
  let rowData = null;
13927
13943
  if(this._subSegment) {
13928
13944
  rowData = this._view.getRowData(this.getRowId());
@@ -13937,32 +13953,27 @@ RowDefinition.prototype.registerToView = function(view, rowId) {
13937
13953
 
13938
13954
  let parentRowId = "";
13939
13955
  let isSegment = this._isChain || this._asSegment;
13940
- if(rowId) {
13941
- parentRowId = view.getSegmentParentRowId(rowId);
13956
+ if(destRowId) {
13957
+ parentRowId = view.getSegmentParentRowId(destRowId);
13942
13958
  if(parentRowId) {
13943
13959
  if(isSegment) { // A chain or a segment cannot be put inside another segment
13944
- rowId = _getEndOfSegmentRowId(view, rowId);
13960
+ destRowId = _getEndOfSegmentRowId(view, destRowId);
13945
13961
  } // else { // Normal row is inserted into a segment
13946
13962
  }
13947
13963
  }
13948
13964
 
13949
13965
  let stalledSorting = _stallSorting(view, isSegment, false);
13950
-
13951
- let newRowId = view.insertRow(rowId, rowData, this.getRowId());
13952
- if(newRowId !== this._rowId) {
13953
- this._rowId = newRowId; // In case there is some duplicate row id
13954
- this._userId = false;
13955
- }
13966
+ view.insertRow(destRowId, rowData, rowId);
13956
13967
 
13957
13968
  if(isSegment) {
13958
- view.setSegmentSeparator(newRowId);
13969
+ view.setSegmentSeparator(rowId);
13959
13970
  _stallSorting(view, false, stalledSorting);
13960
13971
  if(this._collapsed != null) {
13961
- view.collapseSegment(newRowId, this._collapsed);
13972
+ view.collapseSegment(rowId, this._collapsed);
13962
13973
  this._collapsed = null;
13963
13974
  }
13964
13975
  } else if(!this._parent && parentRowId) { // Constituent cannot be added to another segment
13965
- view.addSegmentChild(parentRowId, newRowId, this._dataId);
13976
+ view.addSegmentChild(parentRowId, rowId, this._dataId);
13966
13977
  }
13967
13978
  };
13968
13979
  /** @private
@@ -15522,6 +15533,13 @@ ColumnDefinition.getDataType = function(field) {
15522
15533
  return "";
15523
15534
  };
15524
15535
  /** @public
15536
+ * @ignore
15537
+ * @return {boolean|string|null}
15538
+ */
15539
+ ColumnDefinition.prototype.getTooltipValue = function() {
15540
+ return this._tooltip;
15541
+ };
15542
+ /** @public
15525
15543
  * @return {string}
15526
15544
  */
15527
15545
  ColumnDefinition.prototype.getTooltip = function() {
@@ -18274,6 +18292,10 @@ Cell.prototype._floatingPanel = null;
18274
18292
  * @type {CellFloatingPanel}
18275
18293
  */
18276
18294
  Cell.prototype._frontIcon = null;
18295
+ /** @type {Object}
18296
+ * @private
18297
+ */
18298
+ Cell.prototype._tooltipInfo = null;
18277
18299
 
18278
18300
  //#region ElementWrapper
18279
18301
  /** {@link ElementWrapper#getContent}
@@ -18866,6 +18888,91 @@ Cell.prototype.getClientWidth = function () {
18866
18888
  Cell.prototype.getClientHeight = function () {
18867
18889
  return (this._element) ? this._element.clientHeight : this.getHeight();
18868
18890
  };
18891
+
18892
+ /** To remove the tooltip, pass str as an empty string. To allow cell calculation for the correct tooltip, set str to null.
18893
+ * @public
18894
+ * @param {string|null} str
18895
+ */
18896
+ Cell.prototype.setTooltip = function(str) {
18897
+ this.setTooltipInfo("userTooltip", str);
18898
+ this.updateTooltip();
18899
+ };
18900
+ /** @public
18901
+ * @ignore
18902
+ * @param {string} type
18903
+ * @param {*=} tooltip
18904
+ */
18905
+ Cell.prototype.setTooltipInfo = function(type, tooltip) {
18906
+ let tooltipInfo = this._tooltipInfo;
18907
+ if(!tooltipInfo) {
18908
+ tooltipInfo = this._tooltipInfo = {};
18909
+ }
18910
+
18911
+ tooltipInfo[type] = tooltip;
18912
+ };
18913
+ /** @public
18914
+ * @ignore
18915
+ */
18916
+ Cell.prototype.updateTooltip = function() {
18917
+ let tooltipInfo = this._tooltipInfo;
18918
+ if(!tooltipInfo) {
18919
+ return;
18920
+ }
18921
+
18922
+ let defaultTooltip = "";
18923
+ let customizedTooltip = null;
18924
+
18925
+ // Clipped text tooltip takes precedence over default group header and column tooltip
18926
+ if(tooltipInfo["clippedText"]) { // boolean
18927
+ defaultTooltip = customizedTooltip = tooltipInfo["clippedTextTooltip"];
18928
+ }
18929
+
18930
+ if(tooltipInfo["groupHeaderTooltip"] == null) {
18931
+ if(tooltipInfo["columnDefault"] !== false) {
18932
+ if(tooltipInfo["columnDefault"] != null) { // true, "", string
18933
+ customizedTooltip = tooltipInfo["columnTooltip"];
18934
+ } else { // null
18935
+ defaultTooltip = tooltipInfo["columnTooltip"];
18936
+ }
18937
+ }
18938
+ } else { // Group header tooltip takes precedence over column tooltip
18939
+ if(tooltipInfo["groupHeaderDefault"] !== false) {
18940
+ if(tooltipInfo["groupHeaderDefault"] != null) {
18941
+ customizedTooltip = tooltipInfo["groupHeaderTooltip"];
18942
+ } else {
18943
+ defaultTooltip = tooltipInfo["groupHeaderTooltip"];
18944
+ }
18945
+ }
18946
+ }
18947
+
18948
+ // User tooltip take the highest precedence
18949
+ if(tooltipInfo["userTooltip"] != null) { // "", string
18950
+ customizedTooltip = tooltipInfo["userTooltip"];
18951
+ }
18952
+
18953
+ if(customizedTooltip == null) {
18954
+ customizedTooltip = defaultTooltip;
18955
+ }
18956
+
18957
+ if(customizedTooltip) {
18958
+ if(this.getAttribute("title") !== customizedTooltip) {
18959
+ this.setAttribute("title", customizedTooltip);
18960
+ }
18961
+ } else if(this.getAttribute("title") != null) {
18962
+ this.removeAttribute("title");
18963
+ }
18964
+ };
18965
+ /** @public
18966
+ * @ignore
18967
+ * @param {string} type
18968
+ * @return {*}
18969
+ */
18970
+ Cell.prototype.getTooltipInfo = function(type) {
18971
+ if(this._tooltipInfo) {
18972
+ return this._tooltipInfo[type];
18973
+ }
18974
+ return null;
18975
+ };
18869
18976
  //#region Internal Public Methods
18870
18977
 
18871
18978
  //#region Private Methods
@@ -32017,7 +32124,7 @@ DataView.prototype._updateRowIds = function(opt_rowIds) {
32017
32124
 
32018
32125
  this._excludedRids = {};
32019
32126
  let exclusionCount = 0;
32020
- exclusionCount += DataView._copyObjectKeys(this._excludedRids, this._hiddenRids);
32127
+ exclusionCount += DataView._copyValidObjectKeys(this._excludedRids, this._hiddenRids);
32021
32128
 
32022
32129
  // Segment separators should not be filtered out (hidden)
32023
32130
  let segments = this._dt._getSegmentSeparators();
@@ -32037,7 +32144,7 @@ DataView.prototype._updateRowIds = function(opt_rowIds) {
32037
32144
  }
32038
32145
  this._collapsedRids = segments.getCollapsedRows();
32039
32146
  // Children of collapsed segments must be filtered out (hidden)
32040
- exclusionCount += DataView._copyObjectKeys(this._excludedRids, this._collapsedRids);
32147
+ exclusionCount += DataView._copyValidObjectKeys(this._excludedRids, this._collapsedRids);
32041
32148
  }
32042
32149
 
32043
32150
  if(this._groupLevel > 0 && !opt_rowIds) { // WARNING: The line below is quite slow
@@ -32567,13 +32674,15 @@ DataView._removeArrayItems = function(ary, items) {
32567
32674
  * @param {Object} masterObj
32568
32675
  * @returns {number}
32569
32676
  */
32570
- DataView._copyObjectKeys = function(baseObj, masterObj) {
32677
+ DataView._copyValidObjectKeys = function(baseObj, masterObj) {
32571
32678
  if(masterObj) {
32572
32679
  let count = 0;
32573
32680
 
32574
32681
  for(let key in masterObj) {
32575
- baseObj[key] = 1;
32576
- ++count; // WARNING: duplicated key can be counted more than once
32682
+ if(masterObj[key]) {
32683
+ baseObj[key] = 1;
32684
+ ++count; // WARNING: duplicated key can be counted more than once
32685
+ }
32577
32686
  }
32578
32687
  return count;
32579
32688
  }
@@ -36467,7 +36576,7 @@ Core.prototype._hasPendingRowChange = false;
36467
36576
  * @return {string}
36468
36577
  */
36469
36578
  Core.getVersion = function () {
36470
- return "5.1.117";
36579
+ return "5.1.121";
36471
36580
  };
36472
36581
  /** {@link ElementWrapper#dispose}
36473
36582
  * @override
@@ -45043,11 +45152,11 @@ let _hasFieldOrId = function(colDef, str) {
45043
45152
  };
45044
45153
 
45045
45154
  /** Compare the difference in the 'id' property.
45046
- * @private
45047
- * @param {Object} obj1
45048
- * @param {Object} obj2
45049
- * @returns {boolean} If the id property of two objects is equal, the return will be true, otherwise it will be false.
45050
- */
45155
+ * @private
45156
+ * @param {Object} obj1
45157
+ * @param {Object} obj2
45158
+ * @returns {boolean} If the id property of two objects is equal, the return will be true, otherwise it will be false.
45159
+ */
45051
45160
  let _hasMatchingId = function(obj1, obj2) {
45052
45161
  if(!obj1 || !obj2 || !obj1.id || !obj2.id) { // Handle nullable, if the object or id have null, it's means difference value
45053
45162
  return false;
@@ -45055,6 +45164,25 @@ let _hasMatchingId = function(obj1, obj2) {
45055
45164
  return obj1.id === obj2.id;
45056
45165
  };
45057
45166
 
45167
+ /** @private
45168
+ * @param {Object} e
45169
+ */
45170
+ let _preventDefault = function(e) {
45171
+ if(e) {
45172
+ e.preventDefault();
45173
+ }
45174
+ };
45175
+ /** @private
45176
+ * @param {number=} id
45177
+ * @returns {number} Always return 0
45178
+ */
45179
+ let _clearTimeout = function(id) {
45180
+ if(id) {
45181
+ clearTimeout(id);
45182
+ }
45183
+ return 0;
45184
+ };
45185
+
45058
45186
  /** @constructor
45059
45187
  * @extends {EventDispatcher}
45060
45188
  * @param {(Element|null)=} placeholder
@@ -45365,10 +45493,6 @@ Grid.prototype._topSection = true;
45365
45493
  * @private
45366
45494
  */
45367
45495
  Grid.prototype._focusingArgs = null;
45368
- /** @type {number}
45369
- * @private
45370
- */
45371
- Grid.prototype._scrolledRow = -1;
45372
45496
  /** @type {boolean}
45373
45497
  * @private
45374
45498
  */
@@ -45383,10 +45507,8 @@ Grid.prototype.dispose = function() {
45383
45507
  clearInterval(this._autoLayoutTimer);
45384
45508
  this._autoLayoutTimer = 0;
45385
45509
  }
45386
- if(this._pollingTimerId) {
45387
- clearTimeout(this._pollingTimerId);
45388
- this._pollingTimerId = 0;
45389
- }
45510
+ this._pollingTimerId = _clearTimeout(this._pollingTimerId);
45511
+
45390
45512
  this.removeAllColumns(); // Some conflators are reset
45391
45513
  this.removeAllRows(); // Some conflators are reset
45392
45514
  this._sorter.dispose();
@@ -45409,9 +45531,8 @@ Grid.prototype.dispose = function() {
45409
45531
  }
45410
45532
 
45411
45533
  if(this._focusingArgs) {
45412
- if(this._focusingArgs.id) {
45413
- clearTimeout(this._focusingArgs.id);
45414
- }
45534
+ _clearTimeout(this._focusingArgs.id);
45535
+ _clearTimeout(this._focusingArgs.timeoutId);
45415
45536
  this._focusingArgs = null;
45416
45537
  }
45417
45538
  };
@@ -45716,6 +45837,7 @@ Grid.prototype.initialize = function(gridOption) {
45716
45837
  this.addListener(gridOption, "beforeContentBinding");
45717
45838
  this.addListener(gridOption, "firstRendered");
45718
45839
  this.addListener(gridOption, "afterContentBinding");
45840
+ this.addListener(gridOption, "tabNavigation");
45719
45841
 
45720
45842
  if(gridOption["autoDateConversion"]) {
45721
45843
  t._autoDateConversion = true;
@@ -48232,12 +48354,15 @@ Grid.prototype._renderColumnHeader = function(colIndex, arg) {
48232
48354
  let colName = colDef.getName();
48233
48355
  let colTooltip = colDef.getTooltip();
48234
48356
  let headerAlignment = colDef.getHeaderAlignment();
48357
+ let tooltipValue = colDef.getTooltipValue();
48235
48358
 
48236
48359
  for(let r = 0; r < rowCount; ++r) {
48237
48360
  let tCell = tSection.getCell(colIndex, r, false);
48238
48361
  // Default behaviors
48239
48362
  tCell.setContent(colName);
48240
- tCell.setTooltip(colTooltip);
48363
+ tCell.setTooltipInfo("columnDefault", tooltipValue);
48364
+ tCell.setTooltipInfo("columnTooltip", colTooltip);
48365
+ tCell.updateTooltip();
48241
48366
  tCell.setStyle("textAlign", headerAlignment);
48242
48367
 
48243
48368
  if(customRenderer) {
@@ -48865,6 +48990,8 @@ Grid.prototype._logData = function(rowDefs, options) {
48865
48990
 
48866
48991
  /** @public
48867
48992
  * @description Replace existing row by a new row. Row Id is always changed, after the row is replaced.
48993
+ * If the rowId of the new row is identical to that of the replacing row. Grid will do nothing because
48994
+ * similar rowIds indicate that they are the same row.
48868
48995
  * @param {Grid~RowReference} rowRef Reference (i.e. row index, row id, or row definition) of the insert position
48869
48996
  * @param {(RowDefinition~Options|string)=} rowOption
48870
48997
  * @returns {RowDefinition} Returns null, if the row is not replaced. Otherwise, a newly created row is returned
@@ -48985,38 +49112,49 @@ Grid.prototype.getVScrollView = function () {
48985
49112
  return this._grid.getVScrollView();
48986
49113
  };
48987
49114
 
48988
- /** @private
48989
- * @param {Element} el
48990
- * @return {boolean}
48991
- */
48992
- function isFocusableContent(el) {
48993
- if(el) {
48994
- return (el.tagName !== "SPAN" && !el.disabled);
48995
- }
48996
- return false;
48997
- }
48998
49115
  /** @private
48999
49116
  * @param {Object} cell
49117
+ * @param {Object} args
49000
49118
  * @return {boolean}
49001
49119
  */
49002
- function focusCell(cell) {
49120
+ Grid.prototype._focusCell = function(cell, args) {
49003
49121
  if(cell) {
49004
49122
  let cellContent = cell.getContent();
49005
- if(cellContent && isFocusableContent(cellContent)) {
49006
- cellContent.focus();
49007
- return true;
49123
+ if(cellContent) {
49124
+ let nfe = null;
49125
+ if(this.hasListener("tabNavigation")) {
49126
+ let tabNavArg = {
49127
+ "shiftKey": args.shiftKey,
49128
+ "activeElement": args.activeElement,
49129
+ "cellContent": cellContent,
49130
+ "cell": cell,
49131
+ "colIndex": args.colIndex,
49132
+ "rowIndex": args.rowIndex,
49133
+ "field": args.fields ? args.fields[args.colIndex] : ""
49134
+ };
49135
+ this._dispatch("tabNavigation", tabNavArg);
49136
+ nfe = tabNavArg.nextFocusableElement;
49137
+ } else if(cellContent.tagName !== "SPAN") {
49138
+ nfe = cellContent;
49139
+ }
49140
+
49141
+ if(nfe && nfe !== args.activeElement && !nfe.disabled) {
49142
+ nfe.focus();
49143
+ return true;
49144
+ }
49008
49145
  }
49009
49146
  }
49010
49147
  return false;
49011
- }
49148
+ };
49012
49149
  /** @private
49013
49150
  */
49014
49151
  Grid.prototype._onVScroll = function() {
49015
49152
  let args = this._focusingArgs;
49016
49153
  if(args) {
49154
+ args.timeoutId = _clearTimeout(args.timeoutId);
49017
49155
  this._focusingArgs = null;
49018
49156
  let cell = this._grid.getCell("content", args.colIndex, args.rowIndex);
49019
- if(!focusCell(cell)) {
49157
+ if(!this._focusCell(cell, args)) {
49020
49158
  if(args.shiftKey) {
49021
49159
  this._focusPrevCellContent(args);
49022
49160
  } else {
@@ -49027,6 +49165,11 @@ Grid.prototype._onVScroll = function() {
49027
49165
  };
49028
49166
  /** @private
49029
49167
  */
49168
+ Grid.prototype._onScrollTimeout = function() {
49169
+ this._focusingArgs = null;
49170
+ };
49171
+ /** @private
49172
+ */
49030
49173
  Grid.prototype._selfScrollToRow = function() {
49031
49174
  let args = this._focusingArgs;
49032
49175
  if(args) {
@@ -49036,20 +49179,14 @@ Grid.prototype._selfScrollToRow = function() {
49036
49179
  };
49037
49180
  /** @private
49038
49181
  * @param {Object} args
49039
- * @param {number} colIndex
49040
- * @param {number} rowIndex
49041
49182
  */
49042
- Grid.prototype._requestScroll = function(args, colIndex, rowIndex) {
49043
- if(this._focusingArgs || this._scrolledRow === args.rowIndex) {
49044
- return; // Avoid infinite loop
49183
+ Grid.prototype._requestScroll = function(args) {
49184
+ if(!this._focusingArgs) {
49185
+ this._focusingArgs = args;
49186
+ args.event = null; // The event is invalid after the scroll
49187
+ args.id = setTimeout(this._selfScrollToRow, 0); // Avoid event loop protection
49188
+ args.timeoutId = setTimeout(this._onScrollTimeout, 100); // To avoid a fail case where scroll cannot be performed
49045
49189
  }
49046
-
49047
- this._scrolledRow = args.rowIndex;
49048
- this._focusingArgs = args;
49049
- args.colIndex = colIndex;
49050
- args.rowIndex = rowIndex;
49051
- args.event = null; // The event is invalid after the scroll
49052
- args.id = setTimeout(this._selfScrollToRow); // Avoid event loop protection
49053
49190
  };
49054
49191
  /** @private
49055
49192
  * @param {Object} args
@@ -49073,28 +49210,27 @@ Grid.prototype._focusNextCellContent = function(args) {
49073
49210
  startIdx = i;
49074
49211
  }
49075
49212
  }
49076
- // If the current focus is on a valid content, starts on the next cell
49077
- if(args.event && args.validContent) {
49078
- startIdx++;
49079
- }
49080
49213
 
49081
49214
  let grid = this._grid;
49082
49215
  let section = grid.getSection("content");
49083
49216
  let viewInfo = grid.getVerticalViewInfo();
49084
49217
  let lastFullRow = viewInfo.lastFullRow;
49085
49218
  let rowCount = this.getRowCount();
49219
+
49220
+ args.fields = grid.getColumnFields();
49086
49221
  for(let r = rowIndex; r < rowCount; r++) {
49222
+ args.rowIndex = r;
49087
49223
  for(i = startIdx; i < len; i++) {
49088
49224
  let c = focusableColIndices[i];
49225
+ args.colIndex = c;
49089
49226
  if(r > lastFullRow) {
49090
- this._requestScroll(args, c, r);
49227
+ _preventDefault(args.event);
49228
+ this._requestScroll(args);
49091
49229
  return;
49092
49230
  } else {
49093
49231
  let cell = section.getCell(c, r);
49094
- if(focusCell(cell)) {
49095
- if(args.event) {
49096
- args.event.preventDefault();
49097
- }
49232
+ if(this._focusCell(cell, args)) {
49233
+ _preventDefault(args.event);
49098
49234
  return;
49099
49235
  }
49100
49236
  }
@@ -49102,9 +49238,8 @@ Grid.prototype._focusNextCellContent = function(args) {
49102
49238
  startIdx = 0;
49103
49239
  }
49104
49240
 
49105
- if(args.validContent) { // The current focus on the last focusable content
49106
- this._grid.getHiddenInput().focus();
49107
- }
49241
+ // The current focus on the last focusable content
49242
+ this._grid.getHiddenInput().focus();
49108
49243
  };
49109
49244
  /** @private
49110
49245
  * @param {Object} args
@@ -49128,27 +49263,26 @@ Grid.prototype._focusPrevCellContent = function(args) {
49128
49263
  startIdx = i;
49129
49264
  }
49130
49265
  }
49131
- // If the current focus is on a valid content, starts on the next cell
49132
- if(args.event && args.validContent) {
49133
- --startIdx;
49134
- }
49135
49266
 
49136
49267
  let grid = this._grid;
49137
49268
  let section = grid.getSection("content");
49138
49269
  let viewInfo = grid.getVerticalViewInfo();
49139
49270
  let firstFullRow = viewInfo.firstFullRow;
49271
+
49272
+ args.fields = this.getColumnFields();
49140
49273
  for(let r = rowIndex; r >= 0; r--) {
49274
+ args.rowIndex = r;
49141
49275
  for(i = startIdx; i >= 0; i--) {
49142
49276
  let c = focusableColIndices[i];
49277
+ args.colIndex = c;
49143
49278
  if(r < firstFullRow) {
49144
- this._requestScroll(args, c, r);
49279
+ _preventDefault(args.event);
49280
+ this._requestScroll(args);
49145
49281
  return;
49146
49282
  } else {
49147
49283
  let cell = section.getCell(c, r);
49148
- if(focusCell(cell)) {
49149
- if(args.event) {
49150
- args.event.preventDefault();
49151
- }
49284
+ if(this._focusCell(cell, args)) {
49285
+ _preventDefault(args.event);
49152
49286
  return;
49153
49287
  }
49154
49288
  }
@@ -49156,15 +49290,18 @@ Grid.prototype._focusPrevCellContent = function(args) {
49156
49290
  startIdx = len - 1;
49157
49291
  }
49158
49292
 
49159
- if(args.validContent) { // The current focus on the last focusable content
49160
- this._grid.getHiddenInput(true).focus();
49161
- }
49293
+ // The current focus on the last focusable content
49294
+ this._grid.getHiddenInput(true).focus();
49162
49295
  };
49163
49296
 
49164
49297
  /** @private
49165
49298
  * @param {Object} e
49166
49299
  */
49167
49300
  Grid.prototype._onTabNavigation = function(e) {
49301
+ if(this._focusingArgs) {
49302
+ return; // Cannot do another tab navigation while waiting for scrolling
49303
+ }
49304
+
49168
49305
  let colDefs = this.getColumnDefinitions();
49169
49306
  let colCount = colDefs.length;
49170
49307
 
@@ -49179,19 +49316,8 @@ Grid.prototype._onTabNavigation = function(e) {
49179
49316
  return;
49180
49317
  }
49181
49318
 
49182
- this._scrolledRow = -1; // Reset the scroll loop protector
49183
49319
  let keyEvt = e.event;
49184
49320
  let pos = this.getRelativePosition(keyEvt);
49185
- let validContent = true;
49186
- let activeElement = e.activeElement;
49187
- if(activeElement) {
49188
- validContent = !activeElement.classList.contains("valigner");
49189
- }
49190
-
49191
- if(validContent) {
49192
- let content = pos["cell"] ? pos["cell"].getContent() : null;
49193
- validContent = isFocusableContent(content);
49194
- }
49195
49321
  let startingRowIndex = pos["rowIndex"];
49196
49322
  if(e.onTheEdge) {
49197
49323
  let viewInfo = this._grid.getVerticalViewInfo();
@@ -49203,7 +49329,7 @@ Grid.prototype._onTabNavigation = function(e) {
49203
49329
  colIndex: pos["colIndex"],
49204
49330
  rowIndex: startingRowIndex,
49205
49331
  focusableColIndices: focusableColIndices,
49206
- validContent: validContent
49332
+ activeElement: e.activeElement
49207
49333
  };
49208
49334
 
49209
49335
  if(keyEvt.shiftKey) {
@@ -49213,6 +49339,16 @@ Grid.prototype._onTabNavigation = function(e) {
49213
49339
  }
49214
49340
  };
49215
49341
 
49342
+ /** @public
49343
+ * @ignore
49344
+ * @return {!Object}
49345
+ */
49346
+ Grid.prototype._getEventHandlers = function() {
49347
+ return {
49348
+ "tabNavigation": this._onTabNavigation
49349
+ };
49350
+ };
49351
+
49216
49352
 
49217
49353
  /* harmony default export */ var js_Grid = (Grid);
49218
49354