jquery.dgtable 0.6.0 → 0.6.2

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * jquery.dgtable 0.6.0
2
+ * jquery.dgtable 0.6.2
3
3
  * git://github.com/danielgindi/jquery.dgtable.git
4
4
  */
5
5
  (function (global, factory) {
@@ -5987,7 +5987,46 @@
5987
5987
 
5988
5988
  /** */
5989
5989
 
5990
- var hasOwnProperty$1 = Object.prototype.hasOwnProperty;var
5990
+ var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
5991
+
5992
+ var hasInsertAdjacentElement = Element.prototype.insertAdjacentElement !== undefined;
5993
+
5994
+ function insertBefore(el, before, parent) {
5995
+ if (!before)
5996
+ parent.appendChild(el);else
5997
+ if (hasInsertAdjacentElement === true)
5998
+ before.insertAdjacentElement('beforebegin', el);else
5999
+ parent.insertBefore(el, before);
6000
+ }
6001
+
6002
+ /**
6003
+ *
6004
+ * @param {Element} itemEl
6005
+ * @param {DocumentFragment|null} fragment
6006
+ * @param {Node|undefined} before
6007
+ * @param {Element} itemParent
6008
+ * @returns {DocumentFragment|null}
6009
+ */
6010
+ function insertBeforeWithFragment(itemEl, fragment, before, itemParent) {
6011
+ if (itemEl.parentNode !== itemParent) {
6012
+ if (!fragment)
6013
+ fragment = document.createDocumentFragment();
6014
+ fragment.appendChild(itemEl);
6015
+ } else {
6016
+ // insert fragment
6017
+ if (fragment && fragment.childNodes.length > 0) {
6018
+ insertBefore(fragment, before, itemParent);
6019
+ fragment = null;
6020
+ }
6021
+
6022
+ // insert element
6023
+ if (itemEl.nextSibling !== before) {
6024
+ insertBefore(itemEl, before, itemParent);
6025
+ }
6026
+ }
6027
+
6028
+ return fragment;
6029
+ }var
5991
6030
 
5992
6031
  VirtualListHelper = /*#__PURE__*/function () {
5993
6032
  /**
@@ -6367,6 +6406,7 @@
6367
6406
  var list = p.list;
6368
6407
  var virtual = p.virtual;
6369
6408
  var virtualWrapper = p.virtualWrapper;
6409
+ var itemParent = p.currentItemsParent;
6370
6410
  var scrollTop = list.scrollTop;
6371
6411
  var visibleHeight = list.clientHeight;
6372
6412
  var visibleBottom = scrollTop + visibleHeight;
@@ -6376,123 +6416,172 @@
6376
6416
  var existingEls = p.existingEls;
6377
6417
  var existingCount = existingEls.length;
6378
6418
 
6379
- if (virtual) {(function () {
6380
- var originalWidth = list.clientWidth;
6419
+ if (virtual) {
6420
+ var originalWidth = list.clientWidth;
6381
6421
 
6422
+ if (!virtualWrapper) {
6423
+ virtualWrapper = p.virtualWrapper = p.userItemsParent;
6382
6424
  if (!virtualWrapper) {
6383
- virtualWrapper = p.virtualWrapper = p.userItemsParent;
6384
- if (!virtualWrapper) {
6385
- virtualWrapper = p.virtualWrapper = document.createElement('div');
6386
- list.appendChild(virtualWrapper);
6387
- }
6425
+ virtualWrapper = p.virtualWrapper = document.createElement('div');
6426
+ list.appendChild(virtualWrapper);
6427
+ }
6388
6428
 
6389
- _this._resetCurrentItemsParent();
6429
+ this._resetCurrentItemsParent();
6430
+ itemParent = p.currentItemsParent;
6390
6431
 
6391
- if (p.autoVirtualWrapperWidth) {
6392
- virtualWrapper.style.width = '100%';
6393
- p.virtualWrapperWidthWasSet = true;
6394
- } else {
6395
- p.virtualWrapperWidthWasSet = false;
6396
- }
6432
+ if (p.autoVirtualWrapperWidth) {
6433
+ virtualWrapper.style.width = '100%';
6434
+ p.virtualWrapperWidthWasSet = true;
6435
+ } else {
6436
+ p.virtualWrapperWidthWasSet = false;
6397
6437
  }
6438
+ }
6439
+
6440
+ // Mark all of them for potential reuse
6441
+ for (var i = 0; i < existingCount; i++) {
6442
+ existingEls[i][ReuseElSymbol] = true;
6443
+ }
6444
+
6445
+ // Make sure we have at least estimated positions for all items so we can translate scroll position
6446
+ this._calculateItemPosition(p.count - 1);
6447
+
6448
+ // Find existing elements index range
6449
+ var existingRange = this._getExistingElsRange();
6450
+
6451
+ // Find first visible element
6452
+ var firstVisibleIndex = binarySearchPosition(p.cachedItemPositions, scrollTop);
6453
+ var firstRenderIndex = Math.max(0, firstVisibleIndex - buffer);
6398
6454
 
6399
- // Mark all of them for potential reuse
6400
- for (var i = 0; i < existingCount; i++) {
6401
- existingEls[i][ReuseElSymbol] = true;
6455
+ // Iterate over viewport
6456
+ var index = firstRenderIndex;
6457
+ var renderPos = this._calculateItemPosition(index);
6458
+ var bufferEnd = buffer;
6459
+
6460
+ // we want to render until viewport's bottom + buffer items
6461
+ var maxIndexToRender = Math.max(index, binarySearchPosition(p.cachedItemPositions, visibleBottom - 1) + 1 + buffer);
6462
+
6463
+ var insertedItems = [];
6464
+
6465
+ /** @type DocumentFragment|null */
6466
+ var fragment = null;
6467
+
6468
+ // Find the element to insert before
6469
+ var before = virtualWrapper.childNodes[0];
6470
+
6471
+ var findElementToReuse = function findElementToReuse(index) {
6472
+ // Find existing element to reuse
6473
+ /** @type Element|undefined */
6474
+ var existingEl = undefined;
6475
+
6476
+ if (existingRange.firstIndex !== -1 && index >= existingRange.firstIndex && index <= existingRange.lastIndex) {
6477
+ existingEl = existingEls.find(function (x) {return x[ItemIndexSymbol] === index && x[ReuseElSymbol] === true;});
6402
6478
  }
6403
6479
 
6404
- // Make sure we have at least estimated positions for all items so we can translate scroll position
6405
- _this._calculateItemPosition(p.count - 1);
6480
+ if (existingEl === undefined) {
6481
+ existingEl = (existingRange.firstIndex < firstRenderIndex || existingRange.firstValidArrayIndex > 0 ?
6482
+ existingEls.find(function (x) {return (
6483
+ (x[ItemIndexSymbol] < firstRenderIndex || false === hasOwnProperty$1.call(x, ItemIndexSymbol)) &&
6484
+ x[ReuseElSymbol] === true);}) :
6485
+ undefined) ||
6486
+ findLast(existingEls, function (x) {return x[ReuseElSymbol] === true;});
6487
+ }
6406
6488
 
6407
- // Find existing elements index range
6408
- var existingRange = _this._getExistingElsRange();
6489
+ if (existingEl !== undefined) {
6490
+ delete existingEl[ReuseElSymbol];
6491
+ }
6409
6492
 
6410
- // Find first visible element
6411
- var firstVisibleIndex = binarySearchPosition(p.cachedItemPositions, scrollTop);
6412
- var firstRenderIndex = Math.max(0, firstVisibleIndex - buffer);
6493
+ return existingEl;
6494
+ };
6413
6495
 
6414
- // Iterate over viewport
6415
- var index = firstRenderIndex;
6416
- var renderPos = _this._calculateItemPosition(index);
6417
- var bufferEnd = buffer;
6496
+ // First we iterate and try to add all at once in a fragment, as much as we can.
6497
+ // And then reflow the at once.
6498
+ for (; index < count && index < maxIndexToRender; index++) {
6499
+ var existingEl = findElementToReuse(index);
6418
6500
 
6419
- /** @type Node|undefined */
6420
- var lastEl = undefined;
6501
+ if (before && before === existingEl)
6502
+ before = before.nextSibling;
6421
6503
 
6422
- // If rendering position has not reached the viewport bottom
6423
- // AND we have not rendered all the buffer items yet
6424
- while ((renderPos < visibleBottom || bufferEnd-- > 0) && index < count) {
6425
- // Find existing element to reuse
6426
- /** @type Element|undefined */
6427
- var existingEl = undefined;
6504
+ // Dequeue the element by reusing or creating a new one
6505
+ var itemEl = this._dequeueElementForIndex(existingEl, index, before, true);
6506
+ insertedItems.push([itemEl, index]);
6428
6507
 
6429
- if (existingRange.firstIndex !== -1 && index >= existingRange.firstIndex && index <= existingRange.lastIndex) {
6430
- existingEl = existingEls.find(function (x) {return x[ItemIndexSymbol] === index && x[ReuseElSymbol] === true;});
6431
- }
6508
+ fragment = insertBeforeWithFragment(itemEl, fragment, before, itemParent);
6509
+ }
6432
6510
 
6433
- if (existingEl === undefined) {
6434
- existingEl = (existingRange.firstIndex < firstRenderIndex || existingRange.firstValidArrayIndex > 0 ?
6435
- existingEls.find(function (x) {return (
6436
- (x[ItemIndexSymbol] < firstRenderIndex || false === hasOwnProperty$1.call(x, ItemIndexSymbol)) &&
6437
- x[ReuseElSymbol] === true);}) :
6438
- undefined) ||
6439
- findLast(existingEls, function (x) {return x[ReuseElSymbol] === true;});
6440
- }
6511
+ // Insert any remaining fragment
6512
+ if (fragment && fragment.childNodes.length > 0) {
6513
+ insertBefore(fragment, before, itemParent);
6514
+ }
6441
6515
 
6442
- if (existingEl !== undefined) {
6443
- delete existingEl[ReuseElSymbol];
6444
- }
6516
+ // Iterate on inserted items and reflow them
6517
+ for (var _i = 0, _insertedItems = insertedItems; _i < _insertedItems.length; _i++) {var item = _insertedItems[_i];
6518
+ var _index = item[1];
6519
+ this._insertItemAndFlow(item[0], _index, false /* inserted already */);
6520
+ renderPos = p.cachedItemPositions[_index] + p.cachedItemHeights[_index];
6521
+ }
6522
+
6523
+ // See if we still need to insert more items
6524
+ if (renderPos < visibleBottom) {
6525
+ for (; (renderPos < visibleBottom || bufferEnd-- > 0) && index < count; index++) {
6526
+ var _existingEl = findElementToReuse(index);
6445
6527
 
6446
- // Find the element to insert before
6447
- var insertBefore = lastEl ? lastEl.nextSibling : virtualWrapper.childNodes[0];
6448
- if (insertBefore && insertBefore === existingEl)
6449
- insertBefore = insertBefore.nextSibling;
6528
+ if (before && before === _existingEl)
6529
+ before = before.nextSibling;
6450
6530
 
6451
6531
  // Dequeue the element by reusing or creating a new one
6452
- lastEl = _this._dequeueElementForIndex(existingEl, index, insertBefore);
6532
+ this._dequeueElementForIndex(_existingEl, index, before, false);
6453
6533
 
6454
6534
  // Increment pointers
6455
6535
  renderPos = p.cachedItemPositions[index] + p.cachedItemHeights[index];
6456
- index++;
6457
6536
  }
6537
+ }
6458
6538
 
6459
- // Calculate up to date scroll height
6460
- var scrollHeight = _this.estimateFullHeight();
6461
- p.virtualWrapper.style.height = scrollHeight + 'px';
6539
+ // Calculate up-to-date scroll height
6540
+ var scrollHeight = this.estimateFullHeight();
6541
+ p.virtualWrapper.style.height = scrollHeight + 'px';
6462
6542
 
6463
- if (originalWidth !== list.clientWidth)
6464
- _this.render();})();
6543
+ if (originalWidth !== list.clientWidth)
6544
+ this.render();
6465
6545
  } else {// non-virtual
6466
6546
  if (count !== existingEls.length) {
6467
- for (var i = 0; i < existingCount; i++) {
6468
- existingEls[i][ReuseElSymbol] = true;
6547
+ for (var _i2 = 0; _i2 < existingCount; _i2++) {
6548
+ existingEls[_i2][ReuseElSymbol] = true;
6469
6549
  }
6470
6550
 
6471
- /** @type Node|undefined */
6472
- var lastEl = undefined;var _loop = function _loop(
6473
- index) {
6551
+ // Find the element to insert before
6552
+ var _before = list.childNodes[0];
6553
+
6554
+ /** @type DocumentFragment|null */
6555
+ var _fragment = null;var _loop = function _loop(
6556
+
6557
+ _index2) {
6474
6558
  // Find existing element to reuse
6475
- var existingEl = existingEls.find(function (x) {return x[ItemIndexSymbol] === index && x[ReuseElSymbol] === true;});
6559
+ var existingEl = existingEls.find(function (x) {return x[ItemIndexSymbol] === _index2 && x[ReuseElSymbol] === true;});
6476
6560
 
6477
6561
  if (existingEl !== undefined) {
6478
6562
  delete existingEl[ReuseElSymbol];
6479
6563
  }
6480
6564
 
6481
- // Find the element to insert before
6482
- var insertBefore = lastEl ? lastEl.nextSibling : list.childNodes[0];
6483
- if (insertBefore && insertBefore === existingEl)
6484
- insertBefore = insertBefore.nextSibling;
6565
+ if (_before && _before === existingEl)
6566
+ _before = _before.nextSibling;
6485
6567
 
6486
6568
  // Dequeue the element by reusing or creating a new one
6487
- lastEl = _this._dequeueElementForIndex(existingEl, index, insertBefore);};for (var index = 0; index < count; index++) {_loop(index);
6569
+ var itemEl = _this._dequeueElementForIndex(existingEl, _index2, _before, true);
6570
+
6571
+ _fragment = insertBeforeWithFragment(itemEl, _fragment, _before, itemParent);};for (var _index2 = 0; _index2 < count; _index2++) {_loop(_index2);
6572
+ }
6573
+
6574
+ // Insert any remaining fragment
6575
+ if (_fragment && _fragment.childNodes.length > 0) {
6576
+ insertBefore(_fragment, _before, itemParent);
6488
6577
  }
6489
6578
  }
6490
6579
  }
6491
6580
 
6492
6581
  // Cleanup extra unused elements
6493
6582
  existingCount = existingEls.length; // May have changed
6494
- for (var _i = 0; _i < existingCount; _i++) {
6495
- var el = existingEls[_i];
6583
+ for (var _i3 = 0; _i3 < existingCount; _i3++) {
6584
+ var el = existingEls[_i3];
6496
6585
  if (el[ReuseElSymbol] !== true) continue;
6497
6586
 
6498
6587
  var parent = el.parentNode;
@@ -6500,9 +6589,9 @@
6500
6589
  parent.removeChild(el);
6501
6590
  if (onItemUnrender && el[ItemIndexSymbol] !== undefined)
6502
6591
  onItemUnrender(el);
6503
- existingEls.splice(_i, 1);
6592
+ existingEls.splice(_i3, 1);
6504
6593
 
6505
- _i--;
6594
+ _i3--;
6506
6595
  existingCount--;
6507
6596
  }
6508
6597
  }
@@ -6540,16 +6629,28 @@
6540
6629
  if (existingRange.firstValidArrayIndex === -1)
6541
6630
  return this;
6542
6631
 
6632
+ var itemParent = p.currentItemsParent;
6633
+
6543
6634
  var startIndex = existingRange.firstValidArrayIndex + atIndex - existingRange.firstIndex;
6544
6635
 
6545
6636
  this._pushItemIndexesAt(atIndex, count);
6546
6637
 
6547
6638
  /** @type Node|undefined */
6548
- var lastEl = existingEls[startIndex - 1];
6639
+ var before = existingEls[startIndex - 1] ?
6640
+ existingEls[startIndex - 1].nextSibling :
6641
+ existingEls[0];
6642
+
6643
+ /** @type DocumentFragment|null */
6644
+ var fragment = null;
6549
6645
 
6550
6646
  for (var index = atIndex, end = atIndex + count; index < end; index++) {
6551
- var insertBefore = lastEl ? lastEl.nextSibling : existingEls[0];
6552
- lastEl = this._dequeueElementForIndex(undefined, index, insertBefore);
6647
+ var itemEl = this._dequeueElementForIndex(undefined, index, before, true);
6648
+ fragment = insertBeforeWithFragment(itemEl, fragment, before, itemParent);
6649
+ }
6650
+
6651
+ // Insert any remaining fragment
6652
+ if (fragment && fragment.childNodes.length > 0) {
6653
+ insertBefore(fragment, before, itemParent);
6553
6654
  }
6554
6655
  }
6555
6656
 
@@ -6632,7 +6733,7 @@
6632
6733
  if (index >= existingRange.firstIndex && index <= existingRange.lastIndex) {
6633
6734
  var itemEl = existingEls[existingRange.firstValidArrayIndex + index - existingRange.firstIndex];
6634
6735
  delete itemEl[ItemIndexSymbol];
6635
- this._dequeueElementForIndex(itemEl, index, itemEl.nextSibling);
6736
+ this._dequeueElementForIndex(itemEl, index, itemEl.nextSibling, false);
6636
6737
  }
6637
6738
  }
6638
6739
 
@@ -6775,7 +6876,7 @@
6775
6876
  function createGhostItemElement(ghostIndex, append, ghostTester) {
6776
6877
  var p = this._p;
6777
6878
 
6778
- var itemEl = this._dequeueElementForIndex(null, ghostIndex, false);
6879
+ var itemEl = this._dequeueElementForIndex(null, ghostIndex, false, true);
6779
6880
  try {
6780
6881
  if (append) {
6781
6882
  p.currentItemsParent.appendChild(itemEl);
@@ -7026,13 +7127,14 @@
7026
7127
  * @param {Element|undefined} itemEl
7027
7128
  * @param {number} index
7028
7129
  * @param {Node|boolean|undefined} insertBefore
7130
+ * @param {boolean|undefined} avoidDomReflow
7029
7131
  * @returns {Element}
7030
7132
  * @private
7031
7133
  */ }, { key: "_dequeueElementForIndex", value:
7032
- function _dequeueElementForIndex(itemEl, index, insertBefore) {
7134
+ function _dequeueElementForIndex(itemEl, index, insertBefore, avoidDomReflow) {
7033
7135
  var p = this._p;
7034
7136
  var virtualWrapper = p.virtualWrapper;
7035
- var itemParent = p.currentItemsParent;
7137
+ p.currentItemsParent;
7036
7138
  var existingEls = p.existingEls;
7037
7139
  var onItemRender = p.onItemRender;
7038
7140
  var onItemUnrender = p.onItemUnrender;
@@ -7067,12 +7169,6 @@
7067
7169
  if (!(insertBefore instanceof Node))
7068
7170
  insertBefore = null;
7069
7171
 
7070
- // Insert into DOM
7071
- if (itemEl.parentNode !== itemParent ||
7072
- itemEl.nextSibling !== insertBefore) {
7073
- itemParent.insertBefore(itemEl, insertBefore);
7074
- }
7075
-
7076
7172
  // Remove from existing list
7077
7173
  if (!isNew) {
7078
7174
  var i = existingEls.indexOf(itemEl);
@@ -7088,37 +7184,65 @@
7088
7184
  existingEls.splice(beforeIndex, 0, itemEl);
7089
7185
  }
7090
7186
 
7091
- if (virtualWrapper) {
7092
- // Calculate height
7093
- var itemHeight = itemEl.getBoundingClientRect().height;
7187
+ if (!avoidDomReflow) {
7188
+ this._insertItemAndFlow(itemEl, index, insertBefore);
7189
+ }
7190
+ }
7094
7191
 
7095
- // Put calculated height into cache, and invalidate positions if it's different
7096
- var cachedItemHeight = p.cachedItemHeights[index];
7097
- if (cachedItemHeight !== itemHeight) {
7098
- p.cachedItemHeights[index] = itemHeight;
7099
- }
7192
+ // Add index metadata to item
7193
+ itemEl[ItemIndexSymbol] = index;
7100
7194
 
7101
- if (cachedItemHeight !== undefined && itemHeight !== cachedItemHeight ||
7102
- cachedItemHeight === undefined && itemHeight !== p.cachedItemEstimatedHeights[index]) {
7103
- this._setItemPositionsNeedsUpdate(index + 1);
7104
- }
7195
+ return itemEl;
7196
+ }
7105
7197
 
7106
- // Set item top position
7107
- var pos = this._calculateItemPosition(index);
7108
- var supportedTransform = getSupportedTransform();
7198
+ /**
7199
+ * Insert item element into the DOM, set it's flow in the DOM, and update the item's position. <br />
7200
+ * @param {Element|undefined} itemEl
7201
+ * @param {number} index
7202
+ * @param {Node|boolean|undefined} before
7203
+ * @private
7204
+ */ }, { key: "_insertItemAndFlow", value:
7205
+ function _insertItemAndFlow(itemEl, index, before) {
7206
+ var p = this._p;
7207
+ var virtualWrapper = p.virtualWrapper;
7208
+ var itemParent = p.currentItemsParent;
7109
7209
 
7110
- if (supportedTransform === false) {
7111
- /**@type ElementCSSInlineStyle*/itemEl.style.top = "".concat(pos, "px");
7112
- } else {
7113
- /**@type ElementCSSInlineStyle*/itemEl.style[supportedTransform] = "translateY(".concat(pos, "px)");
7114
- }
7210
+ if (before !== false) {
7211
+ if (!(before instanceof Node))
7212
+ before = null;
7213
+
7214
+ // Insert into DOM
7215
+ if (itemEl.parentNode !== itemParent ||
7216
+ itemEl.nextSibling !== before) {
7217
+ insertBefore(itemEl, before, itemParent);
7115
7218
  }
7116
7219
  }
7117
7220
 
7118
- // Add index metadata to item
7119
- itemEl[ItemIndexSymbol] = index;
7221
+ if (virtualWrapper) {
7222
+ // Calculate height
7223
+ var itemHeight = itemEl.getBoundingClientRect().height;
7120
7224
 
7121
- return itemEl;
7225
+ // Put calculated height into cache, and invalidate positions if it's different
7226
+ var cachedItemHeight = p.cachedItemHeights[index];
7227
+ if (cachedItemHeight !== itemHeight) {
7228
+ p.cachedItemHeights[index] = itemHeight;
7229
+ }
7230
+
7231
+ if (cachedItemHeight !== undefined && itemHeight !== cachedItemHeight ||
7232
+ cachedItemHeight === undefined && itemHeight !== p.cachedItemEstimatedHeights[index]) {
7233
+ this._setItemPositionsNeedsUpdate(index + 1);
7234
+ }
7235
+
7236
+ // Set item top position
7237
+ var pos = this._calculateItemPosition(index);
7238
+ var supportedTransform = getSupportedTransform();
7239
+
7240
+ if (supportedTransform === false) {
7241
+ /**@type ElementCSSInlineStyle*/itemEl.style.top = "".concat(pos, "px");
7242
+ } else {
7243
+ /**@type ElementCSSInlineStyle*/itemEl.style[supportedTransform] = "translateY(".concat(pos, "px)");
7244
+ }
7245
+ }
7122
7246
  }
7123
7247
 
7124
7248
  /**
@@ -7138,10 +7262,10 @@
7138
7262
  break;
7139
7263
  }
7140
7264
 
7141
- for (var _i2 = existingEls.length - 1; _i2 >= 0; _i2--) {
7142
- if (false === hasOwnProperty$1.call(existingEls[_i2], ItemIndexSymbol))
7265
+ for (var _i4 = existingEls.length - 1; _i4 >= 0; _i4--) {
7266
+ if (false === hasOwnProperty$1.call(existingEls[_i4], ItemIndexSymbol))
7143
7267
  continue;
7144
- lastValidArrayIndex = _i2;
7268
+ lastValidArrayIndex = _i4;
7145
7269
  break;
7146
7270
  }
7147
7271
 
@@ -7262,7 +7386,7 @@
7262
7386
  var prefixes = ['transform', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform'];
7263
7387
  var div = document.createElement('div');
7264
7388
  _isTransformSupported = false;
7265
- for (var _i3 = 0, _prefixes = prefixes; _i3 < _prefixes.length; _i3++) {var item = _prefixes[_i3];
7389
+ for (var _i5 = 0, _prefixes = prefixes; _i5 < _prefixes.length; _i5++) {var item = _prefixes[_i5];
7266
7390
  if (div && div.style[item] !== undefined) {
7267
7391
  _isTransformSupported = item;
7268
7392
  break;
@@ -7422,7 +7546,7 @@
7422
7546
  /**
7423
7547
  * @private
7424
7548
  * @field {number} estimatedRowHeight */
7425
- o.estimatedRowHeight = options.estimatedRowHeight === undefined ? 40 : options.estimatedRowHeight;
7549
+ o.estimatedRowHeight = options.estimatedRowHeight || undefined;
7426
7550
 
7427
7551
  /**
7428
7552
  * @private
@@ -7684,7 +7808,7 @@
7684
7808
  autoVirtualWrapperWidth: false,
7685
7809
  virtual: true,
7686
7810
  buffer: o.rowsBufferSize,
7687
- estimatedItemHeight: o.estimatedRowHeight || 40,
7811
+ estimatedItemHeight: o.estimatedRowHeight ? o.estimatedRowHeight : p.virtualRowHeight || 40,
7688
7812
  itemElementCreatorFn: function itemElementCreatorFn() {
7689
7813
  return createElement('div');
7690
7814
  },
@@ -10620,6 +10744,41 @@
10620
10744
 
10621
10745
  var tableClassName = o.tableClassName;
10622
10746
 
10747
+ // Calculate virtual row heights
10748
+ if (o.virtualTable && !p.virtualRowHeight) {
10749
+ var createDummyRow = function createDummyRow() {
10750
+ var row = createElement('div'),
10751
+ cell = row.appendChild(createElement('div')),
10752
+ cellInner = cell.appendChild(createElement('div'));
10753
+ row.className = tableClassName + '-row';
10754
+ cell.className = tableClassName + '-cell';
10755
+ cellInner.innerHTML = '0';
10756
+ row.style.visibility = 'hidden';
10757
+ row.style.position = 'absolute';
10758
+ return row;
10759
+ };
10760
+
10761
+ var $dummyTbody,$dummyWrapper = $('<div>').
10762
+ addClass(that.el.className).
10763
+ css({ 'z-index': -1, 'position': 'absolute', left: '0', top: '-9999px', width: '1px', overflow: 'hidden' }).
10764
+ append(
10765
+ $('<div>').addClass(tableClassName).append(
10766
+ $dummyTbody = $('<div>').addClass(tableClassName + '-body').css('width', 99999)));
10767
+
10768
+
10769
+
10770
+ $dummyWrapper.appendTo(document.body);
10771
+
10772
+ var row1 = createDummyRow(),row2 = createDummyRow(),row3 = createDummyRow();
10773
+ $dummyTbody.append(row1, row2, row3);
10774
+
10775
+ p.virtualRowHeightFirst = Css.getElementHeight(row1, true, true, true);
10776
+ p.virtualRowHeight = Css.getElementHeight(row2, true, true, true);
10777
+ p.virtualRowHeightLast = Css.getElementHeight(row3, true, true, true);
10778
+
10779
+ $dummyWrapper.remove();
10780
+ }
10781
+
10623
10782
  // Create inner table and tbody
10624
10783
  if (!p.$table) {
10625
10784