@refinitiv-ui/efx-grid 6.0.58 → 6.0.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -181,9 +181,9 @@ declare class Grid extends EventDispatcher {
181
181
 
182
182
  public _initDuplicateRicData(rowDef: RowDefinition|null): void;
183
183
 
184
- public insertRow(rowOption?: any, rowRef?: Grid.RowReference|null): any;
184
+ public insertRow(rowOption?: (RowDefinition.Options|string)|null, rowRef?: Grid.RowReference|null): RowDefinition|null;
185
185
 
186
- public insertRows(rowOptions: (any)[]|null, rowRef?: Grid.RowReference|null, opt_fields?: (string)[]|null): void;
186
+ public insertRows(rowOptions: (RowDefinition.Options|string)[]|null, rowRef?: Grid.RowReference|null, opt_fields?: (string)[]|null): void;
187
187
 
188
188
  public addStaticDataRows(dataRows: any[]|null, fields?: (string)[]|null): void;
189
189
 
@@ -323,7 +323,7 @@ declare class Grid extends EventDispatcher {
323
323
 
324
324
  public logDV(opt_options?: any): void;
325
325
 
326
- public replaceRow(rowRef: Grid.RowReference|null, rowOption?: any): any;
326
+ public replaceRow(rowRef: Grid.RowReference|null, rowOption?: (RowDefinition.Options|string)|null): RowDefinition|null;
327
327
 
328
328
  public scrollToColumn(colIndex: number, leftOfView?: boolean|null): boolean;
329
329
 
@@ -1581,16 +1581,16 @@ Grid.prototype.replaceColumn = function (columnOption, colRef) {
1581
1581
  }
1582
1582
 
1583
1583
  var colDef = this.getColumnDefinition(colIndex);
1584
- if(colDef.getChildren()) { // Parent time series field doesn't provide hidden property
1584
+ if(colDef && colDef.getChildren().length > 0) { // Parent time series field doesn't provide hidden property
1585
1585
  colConfig["hidden"] = false;
1586
1586
  }
1587
1587
 
1588
- if(colConfig.id == null) {
1588
+ if(colDef && colConfig.id == null) {
1589
1589
  colConfig.id = colDef.getId(); // retain ID
1590
1590
  }
1591
1591
  this._grid.startBatch("reset");
1592
+ this.removeColumn(colIndex);
1592
1593
  this.insertColumn(colConfig, colIndex);
1593
- this.removeColumn(colIndex + 1); // remove existing column after insert
1594
1594
  this._grid.stopBatch("reset");
1595
1595
  };
1596
1596
 
@@ -2295,9 +2295,9 @@ Grid.prototype._initDuplicateRicData = function(rowDef) {
2295
2295
  }
2296
2296
  };
2297
2297
  /** @public
2298
- * @param {Object=} rowOption
2298
+ * @param {(RowDefinition~Options|string)=} rowOption
2299
2299
  * @param {Grid~RowReference=} rowRef Reference (i.e. row index, row id, or row definition) of the insert position
2300
- * @returns {Object}
2300
+ * @returns {RowDefinition}
2301
2301
  * @example
2302
2302
  * var grid = new rt.Grid(grid_div, options);
2303
2303
  * grid.insertRow({"ric": "RIC"}, 0); // A new row is added at the top
@@ -2328,7 +2328,7 @@ Grid.prototype.insertRow = function(rowOption, rowRef) {
2328
2328
  return rowDef;
2329
2329
  };
2330
2330
  /** @public
2331
- * @param {Array.<Object>} rowOptions Array of row option object
2331
+ * @param {Array.<RowDefinition~Options|string>} rowOptions Array of row option object
2332
2332
  * @param {Grid~RowReference=} rowRef Reference (i.e. row index, row id, or row definition) of the insert position
2333
2333
  * @param {Array.<string>=} opt_fields
2334
2334
  * @example
@@ -3978,8 +3978,8 @@ Grid.prototype._logData = function(rowDefs, options) {
3978
3978
  /** @public
3979
3979
  * @description Replace existing row with a new row. Row ID would be changed, after row is replaced.
3980
3980
  * @param {Grid~RowReference} rowRef Reference (i.e. row index, row id, or row definition) of the insert position
3981
- * @param {Object=} rowOption
3982
- * @returns {Object}
3981
+ * @param {(RowDefinition~Options|string)=} rowOption
3982
+ * @returns {RowDefinition}
3983
3983
  */
3984
3984
  Grid.prototype.replaceRow = function(rowRef, rowOption) {
3985
3985
  var rowId = this._getRowId(rowRef);
@@ -14,7 +14,9 @@ declare namespace ColumnStackPlugin {
14
14
  fields: (string)[]|null,
15
15
  stacks: (ColumnStackPlugin.StackDefinition)[]|null,
16
16
  autoStacking?: boolean|null,
17
- clicked?: ((...params: any[]) => any)|null
17
+ clicked?: ((...params: any[]) => any)|null,
18
+ menuElement?: Element|null,
19
+ menuItemClicked?: ((...params: any[]) => any)|null
18
20
  };
19
21
 
20
22
  type ColumnOptions = {
@@ -10,10 +10,12 @@ import { preventDefault } from "../../tr-grid-util/es6/EventDispatcher.js";
10
10
 
11
11
  /** @typedef {Object} ColumnStackPlugin~Options
12
12
  * @description Available options describing `columnStack` object specified in grid's option
13
- * @property {Array.<string>} fields Fields for stacking. The minimum is 2 fields.
13
+ * @property {Array.<string>} fields Fields for stacking. The minimum is 2 fields
14
14
  * @property {Array.<ColumnStackPlugin~StackDefinition>} stacks List of stacking configuration
15
15
  * @property {boolean=} autoStacking Deprecated. Stacks are automatically maintained as long as its members exist
16
16
  * @property {Function=} clicked=null Event handler when user clicks on stack/expanding icon
17
+ * @property {Element=} menuElement Element used to display a column selection list
18
+ * @property {Function=} menuItemClicked When the menuElement is specified and menu item is clicked, an event handler is called
17
19
  */
18
20
 
19
21
  /** @typedef {Object} ColumnStackPlugin~ColumnOptions
@@ -122,6 +124,7 @@ var ColumnStackPlugin = function () {
122
124
  this._onBeforeBatchOperation = this._onBeforeBatchOperation.bind(this);
123
125
  this._onAfterBatchOperation = this._onAfterBatchOperation.bind(this);
124
126
  this._onPinningChanged = this._onPinningChanged.bind(this);
127
+ this._onMenuItemClicked = this._onMenuItemClicked.bind(this);
125
128
 
126
129
  this._onStackButtonClicked = this._onStackButtonClicked.bind(this);
127
130
  this._updateUI = this._updateUI.bind(this);
@@ -165,6 +168,14 @@ ColumnStackPlugin.prototype._inResetting = false;
165
168
  * @private
166
169
  */
167
170
  ColumnStackPlugin.prototype._inPinning = false;
171
+ /** @type {Element}
172
+ * @private
173
+ */
174
+ ColumnStackPlugin.prototype._menuElement = null;
175
+ /** @type {Function}
176
+ * @private
177
+ */
178
+ ColumnStackPlugin.prototype._menuItemClicked = null;
168
179
 
169
180
  /** @type {number}
170
181
  * @private
@@ -201,12 +212,28 @@ ColumnStackPlugin.prototype.initialize = function (host, options) {
201
212
  if(this._hosts.indexOf(host) >= 0) { return; }
202
213
  this._hosts.push(host);
203
214
 
204
- if(options && options["icons"]) {
205
- var icons = options["icons"]["columnStack"];
206
- if(icons) {
207
- this._stackIconName = icons["stack"];
208
- this._expandIconName = icons["expand"];
209
- this._collapseIconName = icons["collapse"];
215
+ if(options) {
216
+ if(options["icons"]) {
217
+ var icons = options["icons"]["columnStack"];
218
+ if(icons) {
219
+ this._stackIconName = icons["stack"];
220
+ this._expandIconName = icons["expand"];
221
+ this._collapseIconName = icons["collapse"];
222
+ }
223
+ }
224
+
225
+ var opt = options["columnStack"];
226
+ if(opt && this._hosts.length === 1) {
227
+ var menuElement = opt["menuElement"];
228
+ if(menuElement && typeof menuElement === "object" && menuElement.nodeType === 1) {
229
+ menuElement.addEventListener("item-trigger", this._onMenuItemClicked);
230
+ this._menuElement = menuElement;
231
+ }
232
+
233
+ var menuItemClicked = opt["menuItemClicked"];
234
+ if(typeof menuItemClicked === "function") {
235
+ this._menuItemClicked = menuItemClicked;
236
+ }
210
237
  }
211
238
  }
212
239
 
@@ -242,6 +269,10 @@ ColumnStackPlugin.prototype.unload = function (host) {
242
269
  host.unlisten("preSectionRender", this._onPreSectionRender);
243
270
  host.unlisten("pinningChanged", this._onPinningChanged);
244
271
 
272
+ if(this._menuElement) {
273
+ this._menuElement.removeEventListener("item-trigger", this._onMenuItemClicked);
274
+ }
275
+
245
276
  if(this._hosts.length <= 0) {
246
277
  this._conflator.reset();
247
278
  this._groupDefs.removeAllGroups();
@@ -1608,7 +1639,8 @@ ColumnStackPlugin.prototype._onStackButtonClicked = function(e) {
1608
1639
  value: i,
1609
1640
  selected: i === activeIndex,
1610
1641
  label: this.getColumnName(colIndices[i]),
1611
- field: this.getColumnField(colIndices[i])
1642
+ field: this.getColumnField(colIndices[i]),
1643
+ colId: children[i]
1612
1644
  };
1613
1645
  }
1614
1646
  pos["menuData"] = menuData;
@@ -1622,9 +1654,33 @@ ColumnStackPlugin.prototype._onStackButtonClicked = function(e) {
1622
1654
  pos["stackId"] = colData.id;
1623
1655
 
1624
1656
  elem.focus();
1657
+
1658
+ if(this._menuElement && !colData.spreading) {
1659
+ // Populate stack member
1660
+ var button = pos.event.srcElement;
1661
+ var el = this._menuElement;
1662
+ el.data = pos["menuData"];
1663
+ el.positionTarget = button;
1664
+ el.opened = true;
1665
+ }
1625
1666
  this._dispatch("clicked", pos);
1626
1667
  };
1668
+ /** @private
1669
+ * @param {Object} e
1670
+ */
1671
+ ColumnStackPlugin.prototype._onMenuItemClicked = function(e) {
1672
+ if(e.detail) {
1673
+ var selectedIndex = parseInt(e.detail.value, 0);
1674
+ var menuData = this._menuElement.data[selectedIndex];
1675
+ var colId = menuData.colId;
1676
+ this.setActiveColumn(colId);
1677
+ }
1678
+ this._menuElement.opened = false;
1627
1679
 
1680
+ if(this._menuItemClicked) {
1681
+ this._menuItemClicked(e);
1682
+ }
1683
+ };
1628
1684
  /** @public
1629
1685
  * @description Get member column indices in a stack
1630
1686
  * @param {string} stackId
@@ -38,7 +38,8 @@ ElementObserver._getNewId = function () {
38
38
  return id;
39
39
  };
40
40
 
41
- /** @private Observe any element
41
+ /** Observe any element
42
+ * @private
42
43
  * @param {Element} elem
43
44
  * @param {Function} listener
44
45
  * @param {Object=} opt_option
@@ -101,7 +102,8 @@ ElementObserver.addLanguageListener = function(element) {
101
102
  ElementObserver._addObserver(document.documentElement, _onLanguageMutated.bind(null, element));
102
103
  };
103
104
 
104
- /** @public Add a listener to a html attribute
105
+ /** Add a listener to a html attribute
106
+ * @public
105
107
  * @param {Element} element An element within the DOM tree to watch for changes
106
108
  * @param {Function} listener A function which will be called on each attribute change
107
109
  * @param {string=} attributeName If not specified, listener will be called on every attribute change
@@ -63,7 +63,8 @@ ElementWrapper.prototype.getMousePosition = function(e, retObj) {
63
63
  */
64
64
  ElementWrapper.prototype.addEventListener = function(type, listener) {
65
65
  ElementWrapper.base(this, "addEventListener", type, listener);
66
- if(this._elem["on" + type] != null) { // TODO: This won't work with Custom Element
66
+ // TODO: This won't work with Custom Element
67
+ if(this._elem["on" + type] !== undefined) { // eslint-disable-line
67
68
  this._elem.addEventListener(type, listener, false);
68
69
  }
69
70
  };
@@ -74,7 +75,7 @@ ElementWrapper.prototype.addEventListener = function(type, listener) {
74
75
  */
75
76
  ElementWrapper.prototype.removeEventListener = function(type, listener) {
76
77
  ElementWrapper.base(this, "removeEventListener", type, listener);
77
- if(this._elem["on" + type] != null) {
78
+ if(this._elem["on" + type] !== undefined) { // eslint-disable-line
78
79
  this._elem.removeEventListener(type, listener, false);
79
80
  }
80
81
  };
@@ -259,6 +259,11 @@ GridPlugin.prototype.getColumnIndex = function (colRef) {
259
259
  * @return {Array.<number>} column indices
260
260
  */
261
261
  GridPlugin.prototype.getColumnIndices = function (colRefs) {
262
+ var api = this.getGridApi();
263
+ if(api.getColumnIndices) {
264
+ return api.getColumnIndices(colRefs);
265
+ }
266
+
262
267
  // TODO: Unify the below logics
263
268
  if(this._compositeGrid) {
264
269
  var allFields = this._compositeGrid.getColumnFields();
@@ -30,9 +30,9 @@ declare class SubTable extends ElementWrapper {
30
30
 
31
31
  public getAllCells(): (Element)[];
32
32
 
33
- public getAllRows(): HTMLCollection|null;
33
+ public getAllRows(): (Element)[];
34
34
 
35
- public getRows(): HTMLCollection|null;
35
+ public getRows(): (Element)[];
36
36
 
37
37
  public getRow(r: number): Element|null;
38
38
 
@@ -70,5 +70,7 @@ declare class SubTable extends ElementWrapper {
70
70
 
71
71
  declare function tdElem(e: Event|null): number;
72
72
 
73
+ declare function trElem(colIndex: number, rowIndex?: number|null): number;
74
+
73
75
  export default SubTable;
74
76
  export { SubTable };
@@ -49,7 +49,7 @@ SubTable.prototype.addColumns = function(opt_count) {
49
49
 
50
50
  this._colCount += opt_count;
51
51
 
52
- var rows = this.getRows(); // TODO: Must include all suspended rows
52
+ var rows = this._elem.children; // TODO: Must include all suspended rows
53
53
  for(var r = rows.length; --r >= 0;) {
54
54
  var tr = rows[r];
55
55
  for(var c = 0; c < opt_count; ++c) {
@@ -68,7 +68,7 @@ SubTable.prototype.removeColumns = function(opt_count) {
68
68
  if(opt_count <= 0) { return; }
69
69
 
70
70
  this._colCount -= opt_count;
71
- var rows = this.getRows(); // TODO: Must include all suspended rows
71
+ var rows = this._elem.children; // TODO: Must include all suspended rows
72
72
  for(var r = rows.length; --r >= 0;) {
73
73
  Dom.removeChildren(rows[r], opt_count);
74
74
  }
@@ -158,7 +158,7 @@ SubTable.prototype.setDefaultRowHeight = function(val) {
158
158
  this._defaultRowHeight = val;
159
159
  var minHeight = (this._defaultRowHeight != null) ? this._defaultRowHeight + "px" : "";
160
160
 
161
- this._applyDefaultRowHeight(this.getRows(), minHeight);
161
+ this._applyDefaultRowHeight(this._elem.children, minHeight);
162
162
  };
163
163
 
164
164
  /** @public
@@ -194,7 +194,7 @@ SubTable.prototype.getCellsInColumn = function(c) {
194
194
  if(c < 0 || c >= this._colCount) {
195
195
  return null;
196
196
  }
197
- var rows = this.getRows();
197
+ var rows = this._elem.children;
198
198
  var rowCount = rows.length;
199
199
  var ary = new Array(rowCount);
200
200
  for(var r = 0; r < rowCount; ++r) {
@@ -209,13 +209,22 @@ SubTable.prototype.getCellsInColumn = function(c) {
209
209
  */
210
210
  SubTable.prototype.getCellsInRow = function(r) {
211
211
  var tr = this.getRow(r);
212
- return (tr) ? tr.cells : null;
212
+ if(tr) {
213
+ var cells = tr.cells;
214
+ var len = cells.length;
215
+ var ary = new Array(len);
216
+ for(var i = 0; i < len; ++i) {
217
+ ary[i] = cells[i];
218
+ }
219
+ return ary;
220
+ }
221
+ return null;
213
222
  };
214
223
  /** @public
215
224
  * @return {!Array.<Element>} Array of td (HTMLTableCellElement) elements
216
225
  */
217
226
  SubTable.prototype.getAllCells = function() {
218
- var rows = this.getRows();
227
+ var rows = this._elem.children;
219
228
  var rowCount = rows.length;
220
229
  var colCount = this._colCount;
221
230
  var cellCount = 0;
@@ -229,14 +238,20 @@ SubTable.prototype.getAllCells = function() {
229
238
  return ary;
230
239
  };
231
240
  /** @public
232
- * @return {HTMLCollection} Array like collection of tr (HTMLTableRowElement) elements
241
+ * @return {!Array.<Element>} Array of tr (HTMLTableRowElement) elements
233
242
  */
234
243
  SubTable.prototype.getAllRows = function() {
235
- return this._elem.children;
244
+ var chdr = this._elem.children;
245
+ var len = chdr ? chdr.length : 0;
246
+ var ary = new Array(len);
247
+ for(var i = 0; i < len; ++i) {
248
+ ary[i] = chdr[i];
249
+ }
250
+ return ary;
236
251
  };
237
252
  /** @public
238
253
  * @function
239
- * @return {HTMLCollection} Array like collection of tr (HTMLTableRowElement) elements
254
+ * @return {!Array.<Element>} Array of tr (HTMLTableRowElement) elements
240
255
  */
241
256
  SubTable.prototype.getRows = SubTable.prototype.getAllRows;
242
257
  /** @public
@@ -251,7 +266,7 @@ SubTable.prototype.getRow = function(r) {
251
266
  * @return {!Array.<Array.<string>>}
252
267
  */
253
268
  SubTable.prototype.getTextContents = function() {
254
- var rows = this.getRows();
269
+ var rows = this._elem.children;
255
270
  var rowCount = rows.length;
256
271
  var rowContents = new Array(rowCount);
257
272
  for(var r = 0; r < rowCount; ++r) {
@@ -281,7 +296,7 @@ SubTable.prototype.getCellTextContent = function(c, r) {
281
296
  * @return {string}
282
297
  */
283
298
  SubTable.prototype.getColumnTextContent = function(c) { // New-line delimited
284
- var rows = this.getRows();
299
+ var rows = this._elem.children;
285
300
  var rowCount = rows.length;
286
301
  if(c >= 0 && c < this._colCount && rowCount > 0) {
287
302
  var str = rows[0].cells[c].textContent;
@@ -311,7 +326,7 @@ SubTable.prototype.getRowTextContent = function(r) { // Tab delimited
311
326
  * @return {string}
312
327
  */
313
328
  SubTable.prototype.getTableTextContent = function() { // Tab delimited
314
- var rowCount = this.getRows().length;
329
+ var rowCount = this._elem.children.length;
315
330
  if(rowCount > 0) {
316
331
  var str = this.getRowTextContent(0);
317
332
  for(var r = 1; r < rowCount; ++r) {
@@ -326,9 +341,10 @@ SubTable.prototype.getTableTextContent = function() { // Tab delimited
326
341
  */
327
342
  SubTable.prototype.toString = function() {
328
343
  var str = this.getElement().outerHTML;
344
+ str = str.replace(/>\s+</g, "><");
329
345
  str = str.replace(/><tr/g, ">\n\t<tr");
330
346
  str = str.replace(/><td/g, ">\n\t\t<td");
331
- str = str.replace(/><td/g, ">\n\t\t<th"); // TH can occur in thead
347
+ str = str.replace(/><th/g, ">\n\t\t<th"); // TH can occur in thead
332
348
  str = str.replace(/><\/tr/g, ">\n\t</tr");
333
349
  var tagName = this.getElement().tagName.toLowerCase();
334
350
  str = str.replace("</" + tagName, "\n</" + tagName);
@@ -340,39 +356,40 @@ SubTable.prototype.toString = function() {
340
356
  * @return {number}
341
357
  */
342
358
  SubTable.prototype.getColumnIndex = function(e) {
343
- if(e) {
344
- var len, i;
345
- var tgt = /** @type{Node} */(e.target);
346
- if(this._elem.contains(tgt)) {
347
- var tdElem = Dom.closestTagName(tgt, "TD");
348
- if(!tdElem) {
349
- tdElem = Dom.closestTagName(tgt, "TH");
359
+ if(!e) {
360
+ return -1;
361
+ }
362
+ var len, i;
363
+ var tgt = /** @type{Node} */(e.target); // TODO: Support Shadow Root
364
+ if(this._elem.contains(tgt)) {
365
+ var tdElem = Dom.closestTagName(tgt, "TD");
366
+ if(!tdElem) {
367
+ tdElem = Dom.closestTagName(tgt, "TH");
368
+ }
369
+ if(tdElem) {
370
+ var chdr = tdElem.parentElement.children;
371
+ len = chdr.length;
372
+ for(i = 0; i < len; ++i) {
373
+ if(tdElem === chdr[i]) {
374
+ return i;
375
+ }
350
376
  }
351
- if(tdElem) {
352
- var chdr = tdElem.parentElement.children;
353
- len = chdr.length;
377
+ }
378
+ } else { // In case of the target is not a child of this element
379
+ var rows = this._elem.children;
380
+ var cells = (rows[0]) ? rows[0].cells : null;
381
+ if(cells) {
382
+ var pos = Dom.getRelativePosition(e, this._elem);
383
+ var x = pos["x"];
384
+ if(x >= 0) {
385
+ len = cells.length;
354
386
  for(i = 0; i < len; ++i) {
355
- if(tdElem === chdr[i]) {
387
+ x -= cells[i].offsetWidth;
388
+ if(x < 0) { // Not include the right border
356
389
  return i;
357
390
  }
358
391
  }
359
392
  }
360
- } else { // In case of the target is not a child of this element
361
- var rows = this.getRows();
362
- var cells = (rows[0]) ? rows[0].cells : null;
363
- if(cells) {
364
- var pos = Dom.getRelativePosition(e, this._elem);
365
- var x = pos["x"];
366
- if(x >= 0) {
367
- len = cells.length;
368
- for(i = 0; i < len; ++i) {
369
- x -= cells[i].offsetWidth;
370
- if(x < 0) { // Not include the right border
371
- return i;
372
- }
373
- }
374
- }
375
- }
376
393
  }
377
394
  }
378
395
  return -1;
@@ -382,27 +399,36 @@ SubTable.prototype.getColumnIndex = function(e) {
382
399
  * @return {number}
383
400
  */
384
401
  SubTable.prototype.getRowIndex = function(e) {
385
- var rows = this.getRows();
386
- if(rows && e) {
387
- var jLen = rows.length;
388
- var tgtElem = e.target; // TODO: Support Shadow Root
389
- for(var j = 0; j < jLen; ++j) {
390
- var row = rows[j];
391
- if(row === tgtElem) {
392
- return j;
402
+ if(!e) {
403
+ return -1;
404
+ }
405
+ var rows = this._elem.children; // This return HTML collection
406
+ var rowCount = rows ? rows.length : 0;
407
+ if(!rowCount) {
408
+ return -1;
409
+ }
410
+ var i;
411
+ var tgt = /** @type{Node} */(e.target); // TODO: Support Shadow Root
412
+ if(this._elem.contains(tgt)) {
413
+ var trElem = Dom.closestTagName(tgt, "TR");
414
+ if(trElem) {
415
+ for(i = 0; i < rowCount; ++i) {
416
+ var row = rows[i];
417
+ if(row === trElem) {
418
+ return i;
419
+ }
393
420
  }
394
421
  }
422
+ }
395
423
 
396
- // In case of the target is not a child of this element
397
- var pos = Dom.getRelativePosition(e, this._elem);
398
- var y = pos["y"];
399
- if(y >= 0) {
400
- var len = rows.length;
401
- for(var i = 0; i < len; ++i) {
402
- y -= rows[i].offsetHeight;
403
- if(y < 0) { // Not include the right border
404
- return i;
405
- }
424
+ // In case of the target is not a child of this element
425
+ var pos = Dom.getRelativePosition(e, this._elem);
426
+ var y = pos["y"];
427
+ if(y >= 0) {
428
+ for(i = 0; i < rowCount; ++i) {
429
+ y -= rows[i].offsetHeight;
430
+ if(y < 0) { // Not include the right border
431
+ return i;
406
432
  }
407
433
  }
408
434
  }
@@ -458,31 +484,69 @@ SubTable.prototype.setCellRenderer = function(func) {
458
484
  * @param {string=} opt_elementType
459
485
  */
460
486
  SubTable.prototype.cloak = function(elem, opt_elementType) {
461
- SubTable["base"](this, "cloak", elem, "tr");
462
- var rows = elem.getElementsByTagName("TR");
463
- this._colCount = rows[0] ? rows[0].children.length : 0;
487
+ if(elem) {
488
+ this._elem = elem;
489
+ var rows = elem.getElementsByTagName("TR");
490
+ this._colCount = rows[0] ? rows[0].children.length : 0;
491
+ }
464
492
  };
465
493
 
466
494
  /** @public
467
- * @param {number} c1
468
- * @param {number} c2
469
- * @param {number} r1
470
- * @param {number} r2
495
+ * @param {number} c1 Starting column index
496
+ * @param {number} c2 Destination column index
497
+ * @param {number} r1 Starting row index
498
+ * @param {number} r2 Destination row index
471
499
  * @return {Element} Top left cell element
472
500
  */
473
501
  SubTable.prototype.spanBlock = function (c1, c2, r1, r2) { // WARNING: It's c c r r
474
- var cell = null;
475
- for(var c = c2; c >= c1; --c) {
476
- for(var r = r2; r >= r1; --r) {
502
+ var cell = this.getCell(c1, r1);
503
+ if(!cell) {
504
+ return null;
505
+ }
506
+ if(c2 < c1) {
507
+ c2 = c1;
508
+ }
509
+ if(r2 < r1) {
510
+ r2 = r1;
511
+ }
512
+ var curColSpan = +cell.getAttribute("colspan");
513
+ var curRowSpan = +cell.getAttribute("rowspan");
514
+ var c3 = (curColSpan) ? c1 + curColSpan - 1 : c1;
515
+ var r3 = (curRowSpan) ? r1 + curRowSpan - 1 : r1;
516
+
517
+ // TODO: Optimize below logics
518
+ var c, r;
519
+ for(c = c3; c >= c1; --c) {
520
+ for(r = r3; r >= r1; --r) {
521
+ cell = this.getCell(c, r);
522
+ if(cell) {
523
+ cell.style.display = "";
524
+ }
525
+ }
526
+ }
527
+
528
+ for(c = c2; c >= c1; --c) {
529
+ for(r = r2; r >= r1; --r) {
477
530
  cell = this.getCell(c, r);
478
531
  if(cell) {
479
532
  cell.style.display = "none";
480
533
  }
481
534
  }
482
535
  }
483
- if(cell) {
484
- cell.setAttribute("colspan", (c2 - c1 + 1));
485
- cell.setAttribute("rowspan", (r2 - r1 + 1));
536
+
537
+ if(cell) { // The last cell from the loop is the top left cell
538
+ var colSpan = (c2 - c1 + 1);
539
+ var rowSpan = (r2 - r1 + 1);
540
+ if(colSpan > 1) {
541
+ cell.setAttribute("colspan", colSpan);
542
+ } else {
543
+ cell.removeAttribute("colspan");
544
+ }
545
+ if(colSpan > 1) {
546
+ cell.setAttribute("rowspan", rowSpan);
547
+ } else {
548
+ cell.removeAttribute("rowspan");
549
+ }
486
550
  cell.style.display = "";
487
551
  }
488
552
  return cell;
@@ -526,7 +590,7 @@ SubTable.parseTableContent = function(tbl) {
526
590
  };
527
591
 
528
592
  /** @private
529
- * @param {!NodeList<!Element>|Array.<Element>} rows
593
+ * @param {!(NodeList<!Element>|Array.<Element>)} rows
530
594
  * @param {string} minHeight
531
595
  */
532
596
  SubTable.prototype._applyDefaultRowHeight = function(rows, minHeight) {