Index: third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js |
diff --git a/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js |
index 6159e4946800d830b155a8aee6043672e6d24d7d..e8b85f8ac60c7c56d471a24f1e79cfe0faa3500f 100644 |
--- a/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js |
+++ b/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js |
@@ -4,7 +4,8 @@ |
var IOS_TOUCH_SCROLLING = IOS && IOS[1] >= 8; |
var DEFAULT_PHYSICAL_COUNT = 3; |
var HIDDEN_Y = '-10000px'; |
- var DEFAULT_GRID_SIZE = 200; |
+ var ITEM_WIDTH = 0; |
+ var ITEM_HEIGHT = 1; |
var SECRET_TABINDEX = -100; |
Polymer({ |
@@ -236,7 +237,7 @@ |
/** |
* The max number of pages to render. One page is equivalent to the height of the list. |
*/ |
- _maxPages: 3, |
+ _maxPages: 2, |
/** |
* The currently focused physical item. |
@@ -391,10 +392,6 @@ |
return this._viewportHeight * this._maxPages; |
}, |
- get _optPhysicalCount() { |
- return this._estRowsInView * this._itemsPerRow * this._maxPages; |
- }, |
- |
/** |
* True if the current list is visible. |
*/ |
@@ -474,7 +471,6 @@ |
}, |
attached: function() { |
- this.updateViewportBoundaries(); |
if (this._physicalCount === 0) { |
this._debounceTemplate(this._render); |
} |
@@ -504,119 +500,108 @@ |
updateViewportBoundaries: function() { |
this._scrollerPaddingTop = this.scrollTarget === this ? 0 : |
parseInt(window.getComputedStyle(this)['padding-top'], 10); |
- |
+ this._viewportWidth = this.$.items.offsetWidth; |
this._viewportHeight = this._scrollTargetHeight; |
- if (this.grid) { |
- this._updateGridMetrics(); |
- } |
+ this.grid && this._updateGridMetrics(); |
}, |
/** |
- * Update the models, the position of the |
- * items in the viewport and recycle tiles as needed. |
+ * Recycles the physical items when needed. |
*/ |
_scrollHandler: function() { |
- // clamp the `scrollTop` value |
var scrollTop = Math.max(0, Math.min(this._maxScrollTop, this._scrollTop)); |
var delta = scrollTop - this._scrollPosition; |
- var tileHeight, tileTop, kth, recycledTileSet, scrollBottom, physicalBottom; |
- var ratio = this._ratio; |
- var recycledTiles = 0; |
- var hiddenContentSize = this._hiddenContentSize; |
- var currentRatio = ratio; |
- var movingUp = []; |
- |
- // track the last `scrollTop` |
+ var isScrollingDown = delta >= 0; |
+ // Track the current scroll position. |
this._scrollPosition = scrollTop; |
- |
- // clear cached visible indexes |
+ // Clear indexes. |
this._firstVisibleIndexVal = null; |
this._lastVisibleIndexVal = null; |
- scrollBottom = this._scrollBottom; |
- physicalBottom = this._physicalBottom; |
- |
- // random access |
+ // Random access. |
if (Math.abs(delta) > this._physicalSize) { |
- this._physicalTop += delta; |
- recycledTiles = Math.round(delta / this._physicalAverage); |
- } |
- // scroll up |
- else if (delta < 0) { |
- var topSpace = scrollTop - this._physicalTop; |
- var virtualStart = this._virtualStart; |
- |
- recycledTileSet = []; |
- |
- kth = this._physicalEnd; |
- currentRatio = topSpace / hiddenContentSize; |
- |
- // move tiles from bottom to top |
- while ( |
- // approximate `currentRatio` to `ratio` |
- currentRatio < ratio && |
- // recycle less physical items than the total |
- recycledTiles < this._physicalCount && |
- // ensure that these recycled tiles are needed |
- virtualStart - recycledTiles > 0 && |
- // ensure that the tile is not visible |
- physicalBottom - this._getPhysicalSizeIncrement(kth) > scrollBottom |
- ) { |
- |
- tileHeight = this._getPhysicalSizeIncrement(kth); |
- currentRatio += tileHeight / hiddenContentSize; |
- physicalBottom -= tileHeight; |
- recycledTileSet.push(kth); |
- recycledTiles++; |
- kth = (kth === 0) ? this._physicalCount - 1 : kth - 1; |
+ var idxAdjustment = Math.round(delta / this._physicalAverage) * this._itemsPerRow |
+ this._physicalTop = this._physicalTop + delta; |
+ this._virtualStart = this._virtualStart + idxAdjustment; |
+ this._physicalStart = this._physicalStart + idxAdjustment; |
+ this._update(); |
+ } else { |
+ var reusables = this._getReusables(isScrollingDown); |
+ if (isScrollingDown) { |
+ this._physicalTop = reusables.physicalTop; |
+ this._virtualStart = this._virtualStart + reusables.indexes.length; |
+ this._physicalStart = this._physicalStart + reusables.indexes.length; |
+ } else { |
+ this._virtualStart = this._virtualStart - reusables.indexes.length; |
+ this._physicalStart = this._physicalStart - reusables.indexes.length; |
} |
- |
- movingUp = recycledTileSet; |
- recycledTiles = -recycledTiles; |
- } |
- // scroll down |
- else if (delta > 0) { |
- var bottomSpace = physicalBottom - scrollBottom; |
- var virtualEnd = this._virtualEnd; |
- var lastVirtualItemIndex = this._virtualCount-1; |
- |
- recycledTileSet = []; |
- |
- kth = this._physicalStart; |
- currentRatio = bottomSpace / hiddenContentSize; |
- |
- // move tiles from top to bottom |
- while ( |
- // approximate `currentRatio` to `ratio` |
- currentRatio < ratio && |
- // recycle less physical items than the total |
- recycledTiles < this._physicalCount && |
- // ensure that these recycled tiles are needed |
- virtualEnd + recycledTiles < lastVirtualItemIndex && |
- // ensure that the tile is not visible |
- this._physicalTop + this._getPhysicalSizeIncrement(kth) < scrollTop |
- ) { |
- |
- tileHeight = this._getPhysicalSizeIncrement(kth); |
- currentRatio += tileHeight / hiddenContentSize; |
- |
- this._physicalTop += tileHeight; |
- recycledTileSet.push(kth); |
- recycledTiles++; |
- kth = (kth + 1) % this._physicalCount; |
+ if (reusables.indexes.length === 0) { |
+ this._increasePoolIfNeeded(); |
+ } else { |
+ this._update(reusables.indexes, isScrollingDown ? null : reusables.indexes); |
} |
} |
+ }, |
- if (recycledTiles === 0) { |
- // Try to increase the pool if the list's client isn't filled up with physical items |
- if (physicalBottom < scrollBottom || this._physicalTop > scrollTop) { |
- this._increasePoolIfNeeded(); |
- } |
+ /** |
+ * Returns an object that contains the indexes of the physical items |
+ * that might be reused and the physicalTop. |
+ * |
+ * @param {boolean} fromTop If the potential reusable items are above the scrolling region. |
+ */ |
+ _getReusables: function(fromTop) { |
+ var ith, lastIth, offsetContent, physicalItemHeight; |
+ var idxs = []; |
+ var protectedOffsetContent = this._hiddenContentSize * this._ratio; |
+ var virtualStart = this._virtualStart; |
+ var virtualEnd = this._virtualEnd; |
+ var physicalCount = this._physicalCount; |
+ var physicalTop = this._physicalTop; |
+ var scrollTop = this._scrollTop; |
+ var scrollBottom = this._scrollBottom; |
+ |
+ if (fromTop) { |
+ ith = this._physicalStart; |
+ lastIth = this._physicalEnd; |
+ offsetContent = scrollTop - physicalTop; |
} else { |
- this._virtualStart = this._virtualStart + recycledTiles; |
- this._physicalStart = this._physicalStart + recycledTiles; |
- this._update(recycledTileSet, movingUp); |
+ ith = this._physicalEnd; |
+ lastIth = this._physicalStart; |
+ offsetContent = this._physicalBottom - scrollBottom; |
+ } |
+ while (true) { |
+ physicalItemHeight = this._getPhysicalSizeIncrement(ith); |
+ offsetContent = offsetContent - physicalItemHeight; |
+ if (idxs.length >= physicalCount || offsetContent <= protectedOffsetContent) { |
+ break; |
+ } |
+ if (fromTop) { |
+ // Check that index is within the valid range. |
+ if (virtualEnd + idxs.length + 1 >= this._virtualCount) { |
+ break; |
+ } |
+ // Check that the index is not visible. |
+ if (physicalTop + physicalItemHeight >= scrollTop) { |
+ break; |
+ } |
+ idxs.push(ith); |
+ physicalTop = physicalTop + physicalItemHeight; |
+ ith = (ith + 1) % physicalCount; |
+ } else { |
+ // Check that index is within the valid range. |
+ if (virtualStart - idxs.length <= 0) { |
+ break; |
+ } |
+ // Check that the index is not visible. |
+ if (physicalTop + this._physicalSize - physicalItemHeight <= scrollBottom) { |
+ break; |
+ } |
+ idxs.push(ith); |
+ physicalTop = physicalTop - physicalItemHeight; |
+ ith = (ith === 0) ? physicalCount - 1 : ith - 1; |
+ } |
} |
+ return { indexes: idxs, physicalTop: physicalTop }; |
}, |
/** |
@@ -625,6 +610,9 @@ |
* @param {!Array<number>=} movingUp |
*/ |
_update: function(itemSet, movingUp) { |
+ if (itemSet && itemSet.length === 0) { |
+ return; |
+ } |
this._manageFocus(); |
this._assignModels(itemSet); |
this._updateMetrics(itemSet); |
@@ -736,13 +724,20 @@ |
}, |
/** |
- * Render a new list of items. |
+ * Renders the a new list. |
*/ |
_render: function() { |
if (this.isAttached && this._isVisible) { |
if (this._physicalCount === 0) { |
+ this.updateViewportBoundaries(); |
this._increasePool(DEFAULT_PHYSICAL_COUNT); |
} else { |
+ // Try to recycle nodes |
+ var reusables = this._getReusables(true); |
+ this._physicalTop = reusables.physicalTop; |
+ this._virtualStart = this._virtualStart + reusables.indexes.length; |
+ this._physicalStart = this._physicalStart + reusables.indexes.length; |
+ this._update(reusables.indexes); |
this._update(); |
} |
} |
@@ -878,6 +873,7 @@ |
} else if (change.path === 'items.splices') { |
this._adjustVirtualIndex(change.value.indexSplices); |
this._virtualCount = this.items ? this.items.length : 0; |
+ |
this._debounceTemplate(this._render); |
} else { |
@@ -972,7 +968,6 @@ |
var el = this._physicalItems[pidx]; |
var inst = el._templateInstance; |
var item = this.items && this.items[vidx]; |
- |
if (item != null) { |
inst[this.as] = item; |
inst.__key__ = this._collection.getKey(item); |
@@ -1004,22 +999,18 @@ |
var prevPhysicalAvg = this._physicalAverage; |
this._iterateItems(function(pidx, vidx) { |
- |
oldPhysicalSize += this._physicalSizes[pidx] || 0; |
this._physicalSizes[pidx] = this._physicalItems[pidx].offsetHeight; |
newPhysicalSize += this._physicalSizes[pidx]; |
this._physicalAverageCount += this._physicalSizes[pidx] ? 1 : 0; |
- |
}, itemSet); |
- |
- this._viewportHeight = this._scrollTargetHeight; |
+ |
if (this.grid) { |
this._updateGridMetrics(); |
this._physicalSize = Math.ceil(this._physicalCount / this._itemsPerRow) * this._rowHeight; |
} else { |
this._physicalSize = this._physicalSize + newPhysicalSize - oldPhysicalSize; |
} |
- |
// Update the average if it measured something. |
if (this._physicalAverageCount !== prevAvgCount) { |
this._physicalAverage = Math.round( |
@@ -1029,12 +1020,8 @@ |
}, |
_updateGridMetrics: function() { |
- this._viewportWidth = this.$.items.offsetWidth; |
- // Set item width to the value of the _physicalItems offsetWidth |
- this._itemWidth = this._physicalCount > 0 ? this._physicalItems[0].getBoundingClientRect().width : DEFAULT_GRID_SIZE; |
- // Set row height to the value of the _physicalItems offsetHeight |
- this._rowHeight = this._physicalCount > 0 ? this._physicalItems[0].offsetHeight : DEFAULT_GRID_SIZE; |
- // If in grid mode compute how many items with exist in each row |
+ this._itemWidth = this._physicalCount > 0 ? this._physicalItems[0].getBoundingClientRect().width : 200; |
+ this._rowHeight = this._physicalCount > 0 ? this._physicalItems[0].offsetHeight : 200; |
this._itemsPerRow = this._itemWidth ? Math.floor(this._viewportWidth / this._itemWidth) : this._itemsPerRow; |
}, |
@@ -1219,10 +1206,14 @@ |
Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', function() { |
this.updateViewportBoundaries(); |
this._render(); |
- |
- if (this._physicalCount > 0 && this._isVisible) { |
- this._resetAverage(); |
- this.scrollToIndex(this.firstVisibleIndex); |
+ if (this._isVisible) { |
+ this.toggleScrollListener(true); |
+ if (this._physicalCount > 0) { |
+ this._resetAverage(); |
+ this.scrollToIndex(this.firstVisibleIndex); |
+ } |
+ } else { |
+ this.toggleScrollListener(false); |
} |
}.bind(this), 1)); |
}, |
@@ -1365,7 +1356,6 @@ |
model.tabIndex = SECRET_TABINDEX; |
activeElTabIndex = activeEl ? activeEl.tabIndex : -1; |
model.tabIndex = modelTabIndex; |
- |
// Only select the item if the tap wasn't on a focusable child |
// or the element bound to `tabIndex` |
if (activeEl && physicalItem !== activeEl && physicalItem.contains(activeEl) && activeElTabIndex !== SECRET_TABINDEX) { |
@@ -1446,7 +1436,6 @@ |
var physicalItem = this._physicalItems[this._getPhysicalIndex(idx)]; |
var model = physicalItem._templateInstance; |
var focusable; |
- |
// set a secret tab index |
model.tabIndex = SECRET_TABINDEX; |
// check if focusable element is the physical item |