Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(222)

Unified Diff: third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js

Issue 2386533002: MD History: update iron-list and dependencies for better scroll performance (Closed)
Patch Set: test "fixes" Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698