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 8a0ee8717684870bad9d3a5fb4e848f60407a7ad..6bcafe8ffc8be313ebf6a5ed878ffa2815bcb841 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 |
@@ -118,7 +118,7 @@ |
_ratio: 0.5, |
/** |
- * The padding-top value of the `scroller` element |
+ * The padding-top value for the list. |
*/ |
_scrollerPaddingTop: 0, |
@@ -128,21 +128,6 @@ |
_scrollPosition: 0, |
/** |
- * The number of tiles in the DOM. |
- */ |
- _physicalCount: 0, |
- |
- /** |
- * The k-th tile that is at the top of the scrolling list. |
- */ |
- _physicalStart: 0, |
- |
- /** |
- * The k-th tile that is at the bottom of the scrolling list. |
- */ |
- _physicalEnd: 0, |
- |
- /** |
* The sum of the heights of all the tiles in the DOM. |
*/ |
_physicalSize: 0, |
@@ -169,11 +154,6 @@ |
_virtualCount: 0, |
/** |
- * The n-th item rendered in the `_physicalStart` tile. |
- */ |
- _virtualStartVal: 0, |
- |
- /** |
* A map between an item key and its physical item index |
*/ |
_physicalIndexForKey: null, |
@@ -219,7 +199,6 @@ |
*/ |
_lastVisibleIndexVal: null, |
- |
/** |
* A Polymer collection for the items. |
* @type {?Polymer.Collection} |
@@ -243,9 +222,14 @@ |
_maxPages: 3, |
/** |
- * The currently focused item index. |
+ * The currently focused physical item. |
*/ |
- _focusedIndex: 0, |
+ _focusedItem: null, |
+ |
+ /** |
+ * The index of the `_focusedItem`. |
+ */ |
+ _focusedIndex: -1, |
/** |
* The the item that is focused if it is moved offscreen. |
@@ -281,6 +265,20 @@ |
}, |
/** |
+ * The height of the physical content that isn't on the screen. |
+ */ |
+ get _hiddenContentSize() { |
+ return this._physicalSize - this._viewportSize; |
+ }, |
+ |
+ /** |
+ * The maximum scroll top value. |
+ */ |
+ get _maxScrollTop() { |
+ return this._estScrollHeight - this._viewportSize + this._scrollerPaddingTop; |
+ }, |
+ |
+ /** |
* The lowest n-th value for an item such that it can be rendered in `_physicalStart`. |
*/ |
_minVirtualStart: 0, |
@@ -293,42 +291,55 @@ |
}, |
/** |
- * The height of the physical content that isn't on the screen. |
+ * The n-th item rendered in the `_physicalStart` tile. |
*/ |
- get _hiddenContentSize() { |
- return this._physicalSize - this._viewportSize; |
+ _virtualStartVal: 0, |
+ |
+ set _virtualStart(val) { |
+ this._virtualStartVal = Math.min(this._maxVirtualStart, Math.max(this._minVirtualStart, val)); |
}, |
- /** |
- * The maximum scroll top value. |
- */ |
- get _maxScrollTop() { |
- return this._estScrollHeight - this._viewportSize; |
+ get _virtualStart() { |
+ return this._virtualStartVal || 0; |
}, |
/** |
- * Sets the n-th item rendered in `_physicalStart` |
+ * The k-th tile that is at the top of the scrolling list. |
*/ |
- set _virtualStart(val) { |
- // clamp the value so that _minVirtualStart <= val <= _maxVirtualStart |
- this._virtualStartVal = Math.min(this._maxVirtualStart, Math.max(this._minVirtualStart, val)); |
- if (this._physicalCount === 0) { |
- this._physicalStart = 0; |
- this._physicalEnd = 0; |
- } else { |
- this._physicalStart = this._virtualStartVal % this._physicalCount; |
- this._physicalEnd = (this._physicalStart + this._physicalCount - 1) % this._physicalCount; |
+ _physicalStartVal: 0, |
+ |
+ set _physicalStart(val) { |
+ this._physicalStartVal = val % this._physicalCount; |
+ if (this._physicalStartVal < 0) { |
+ this._physicalStartVal = this._physicalCount + this._physicalStartVal; |
} |
+ this._physicalEnd = (this._physicalStart + this._physicalCount - 1) % this._physicalCount; |
+ }, |
+ |
+ get _physicalStart() { |
+ return this._physicalStartVal || 0; |
}, |
/** |
- * Gets the n-th item rendered in `_physicalStart` |
+ * The number of tiles in the DOM. |
*/ |
- get _virtualStart() { |
- return this._virtualStartVal; |
+ _physicalCountVal: 0, |
+ |
+ set _physicalCount(val) { |
+ this._physicalCountVal = val; |
+ this._physicalEnd = (this._physicalStart + this._physicalCount - 1) % this._physicalCount; |
+ }, |
+ |
+ get _physicalCount() { |
+ return this._physicalCountVal; |
}, |
/** |
+ * The k-th tile that is at the bottom of the scrolling list. |
+ */ |
+ _physicalEnd: 0, |
+ |
+ /** |
* An optimal physical size such that we will have enough physical items |
* to fill up the viewport and recycle when the user scrolls. |
* |
@@ -353,12 +364,11 @@ |
*/ |
get firstVisibleIndex() { |
if (this._firstVisibleIndexVal === null) { |
- var physicalOffset = this._physicalTop; |
+ var physicalOffset = this._physicalTop + this._scrollerPaddingTop; |
this._firstVisibleIndexVal = this._iterateItems( |
function(pidx, vidx) { |
physicalOffset += this._physicalSizes[pidx]; |
- |
if (physicalOffset > this._scrollPosition) { |
return vidx; |
} |
@@ -379,14 +389,18 @@ |
this._iterateItems(function(pidx, vidx) { |
physicalOffset += this._physicalSizes[pidx]; |
- if(physicalOffset <= this._scrollBottom) { |
- this._lastVisibleIndexVal = vidx; |
+ if (physicalOffset <= this._scrollBottom) { |
+ this._lastVisibleIndexVal = vidx; |
} |
}); |
} |
return this._lastVisibleIndexVal; |
}, |
+ get _defaultScrollTarget() { |
+ return this; |
+ }, |
+ |
ready: function() { |
this.addEventListener('focus', this._didFocus.bind(this), true); |
}, |
@@ -400,10 +414,6 @@ |
this._itemsRendered = false; |
}, |
- get _defaultScrollTarget() { |
- return this; |
- }, |
- |
/** |
* Set the overflow property if this element has its own scrolling region |
*/ |
@@ -419,8 +429,9 @@ |
* @method updateViewportBoundaries |
*/ |
updateViewportBoundaries: function() { |
- var scrollerStyle = window.getComputedStyle(this.scrollTarget); |
- this._scrollerPaddingTop = parseInt(scrollerStyle['padding-top'], 10); |
+ this._scrollerPaddingTop = this.scrollTarget === this ? 0 : |
+ parseInt(window.getComputedStyle(this)['padding-top'], 10); |
+ |
this._viewportSize = this._scrollTargetHeight; |
}, |
@@ -430,12 +441,10 @@ |
*/ |
_scrollHandler: function() { |
// clamp the `scrollTop` value |
- // IE 10|11 scrollTop may go above `_maxScrollTop` |
- // iOS `scrollTop` may go below 0 and above `_maxScrollTop` |
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 delta = scrollTop - this._scrollPosition; |
var recycledTiles = 0; |
var hiddenContentSize = this._hiddenContentSize; |
var currentRatio = ratio; |
@@ -444,7 +453,7 @@ |
// track the last `scrollTop` |
this._scrollPosition = scrollTop; |
- // clear cached visible index |
+ // clear cached visible indexes |
this._firstVisibleIndexVal = null; |
this._lastVisibleIndexVal = null; |
@@ -531,6 +540,7 @@ |
} |
} else { |
this._virtualStart = this._virtualStart + recycledTiles; |
+ this._physicalStart = this._physicalStart + recycledTiles; |
this._update(recycledTileSet, movingUp); |
} |
}, |
@@ -542,11 +552,7 @@ |
*/ |
_update: function(itemSet, movingUp) { |
// manage focus |
- if (this._isIndexRendered(this._focusedIndex)) { |
- this._restoreFocusedItem(); |
- } else { |
- this._createFocusBackfillItem(); |
- } |
+ this._manageFocus(); |
// update models |
this._assignModels(itemSet); |
// measure heights |
@@ -613,7 +619,6 @@ |
* Increases the pool size. |
*/ |
_increasePool: function(missingItems) { |
- // limit the size |
var nextPhysicalCount = Math.min( |
this._physicalCount + missingItems, |
this._virtualCount - this._virtualStart, |
@@ -622,14 +627,24 @@ |
var prevPhysicalCount = this._physicalCount; |
var delta = nextPhysicalCount - prevPhysicalCount; |
- if (delta > 0) { |
- [].push.apply(this._physicalItems, this._createPool(delta)); |
- [].push.apply(this._physicalSizes, new Array(delta)); |
+ if (delta <= 0) { |
+ return; |
+ } |
+ |
+ [].push.apply(this._physicalItems, this._createPool(delta)); |
+ [].push.apply(this._physicalSizes, new Array(delta)); |
+ |
+ this._physicalCount = prevPhysicalCount + delta; |
- this._physicalCount = prevPhysicalCount + delta; |
- // tail call |
- return this._update(); |
+ // update the physical start if we need to preserve the model of the focused item. |
+ // In this situation, the focused item is currently rendered and its model would |
+ // have changed after increasing the pool if the physical start remained unchanged. |
+ if (this._physicalStart > this._physicalEnd && |
+ this._isIndexRendered(this._focusedIndex) && |
+ this._getPhysicalIndex(this._focusedIndex) < this._physicalEnd) { |
+ this._physicalStart = this._physicalStart + delta; |
} |
+ this._update(); |
}, |
/** |
@@ -718,27 +733,36 @@ |
/** |
* Called as a side effect of a host items.<key>.<path> path change, |
- * responsible for notifying item.<path> changes to row for key. |
+ * responsible for notifying item.<path> changes. |
*/ |
_forwardItemPath: function(path, value) { |
- if (this._physicalIndexForKey) { |
- var dot = path.indexOf('.'); |
- var key = path.substring(0, dot < 0 ? path.length : dot); |
- var idx = this._physicalIndexForKey[key]; |
- var row = this._physicalItems[idx]; |
- |
- if (idx === this._focusedIndex && this._offscreenFocusedItem) { |
- row = this._offscreenFocusedItem; |
- } |
- if (row) { |
- var inst = row._templateInstance; |
- if (dot >= 0) { |
- path = this.as + '.' + path.substring(dot+1); |
- inst.notifyPath(path, value, true); |
- } else { |
- inst[this.as] = value; |
- } |
- } |
+ if (!this._physicalIndexForKey) { |
+ return; |
+ } |
+ var inst; |
+ var dot = path.indexOf('.'); |
+ var key = path.substring(0, dot < 0 ? path.length : dot); |
+ var idx = this._physicalIndexForKey[key]; |
+ var el = this._physicalItems[idx]; |
+ |
+ |
+ if (idx === this._focusedIndex && this._offscreenFocusedItem) { |
+ el = this._offscreenFocusedItem; |
+ } |
+ if (!el) { |
+ return; |
+ } |
+ |
+ inst = el._templateInstance; |
+ |
+ if (inst.__key__ !== key) { |
+ return; |
+ } |
+ if (dot >= 0) { |
+ path = this.as + '.' + path.substring(dot+1); |
+ inst.notifyPath(path, value, true); |
+ } else { |
+ inst[this.as] = value; |
} |
}, |
@@ -748,19 +772,15 @@ |
*/ |
_itemsChanged: function(change) { |
if (change.path === 'items') { |
- |
- this._restoreFocusedItem(); |
- // render the new set |
- this._itemsRendered = false; |
- // update the whole set |
+ // reset items |
this._virtualStart = 0; |
this._physicalTop = 0; |
this._virtualCount = this.items ? this.items.length : 0; |
- this._focusedIndex = 0; |
this._collection = this.items ? Polymer.Collection.get(this.items) : null; |
this._physicalIndexForKey = {}; |
this._resetScrollPosition(0); |
+ this._removeFocusedItem(); |
// create the initial physical items |
if (!this._physicalItems) { |
@@ -768,47 +788,50 @@ |
this._physicalItems = this._createPool(this._physicalCount); |
this._physicalSizes = new Array(this._physicalCount); |
} |
- this._debounceTemplate(this._render); |
+ |
+ this._physicalStart = 0; |
} else if (change.path === 'items.splices') { |
- // render the new set |
- this._itemsRendered = false; |
this._adjustVirtualIndex(change.value.indexSplices); |
this._virtualCount = this.items ? this.items.length : 0; |
- this._debounceTemplate(this._render); |
- |
- if (this._focusedIndex < 0 || this._focusedIndex >= this._virtualCount) { |
- this._focusedIndex = 0; |
- } |
- this._debounceTemplate(this._render); |
- |
} else { |
// update a single item |
this._forwardItemPath(change.path.split('.').slice(1).join('.'), change.value); |
+ return; |
} |
+ |
+ this._itemsRendered = false; |
+ this._debounceTemplate(this._render); |
}, |
/** |
* @param {!Array<!PolymerSplice>} splices |
*/ |
_adjustVirtualIndex: function(splices) { |
- var i, splice, idx; |
- |
- for (i = 0; i < splices.length; i++) { |
- splice = splices[i]; |
- |
+ splices.forEach(function(splice) { |
// deselect removed items |
- splice.removed.forEach(this.$.selector.deselect, this.$.selector); |
- |
- idx = splice.index; |
+ splice.removed.forEach(this._removeItem, this); |
// We only need to care about changes happening above the current position |
- if (idx >= this._virtualStart) { |
- break; |
+ if (splice.index < this._virtualStart) { |
+ var delta = Math.max( |
+ splice.addedCount - splice.removed.length, |
+ splice.index - this._virtualStart); |
+ |
+ this._virtualStart = this._virtualStart + delta; |
+ |
+ if (this._focusedIndex >= 0) { |
+ this._focusedIndex = this._focusedIndex + delta; |
+ } |
} |
+ }, this); |
+ }, |
- this._virtualStart = this._virtualStart + |
- Math.max(splice.addedCount - splice.removed.length, idx - this._virtualStart); |
+ _removeItem: function(item) { |
+ this.$.selector.deselect(item); |
+ // remove the current focused item |
+ if (this._focusedItem && this._focusedItem._templateInstance[this.as] === item) { |
+ this._removeFocusedItem(); |
} |
}, |
@@ -861,19 +884,18 @@ |
var inst = el._templateInstance; |
var item = this.items && this.items[vidx]; |
- if (item !== undefined && item !== null) { |
+ if (item != null) { |
inst[this.as] = item; |
inst.__key__ = this._collection.getKey(item); |
inst[this.selectedAs] = /** @type {!ArraySelectorElement} */ (this.$.selector).isSelected(item); |
inst[this.indexAs] = vidx; |
- inst.tabIndex = vidx === this._focusedIndex ? 0 : -1; |
- el.removeAttribute('hidden'); |
+ inst.tabIndex = this._focusedIndex === vidx ? 0 : -1; |
this._physicalIndexForKey[inst.__key__] = pidx; |
+ el.removeAttribute('hidden'); |
} else { |
inst.__key__ = null; |
el.setAttribute('hidden', ''); |
} |
- |
}, itemSet); |
}, |
@@ -921,10 +943,8 @@ |
var y = this._physicalTop; |
this._iterateItems(function(pidx) { |
- |
this.translate3d(0, y + 'px', 0, this._physicalItems[pidx]); |
y += this._physicalSizes[pidx]; |
- |
}); |
}, |
@@ -972,7 +992,6 @@ |
this._scrollHeight = this._estScrollHeight; |
} |
}, |
- |
/** |
* Scroll to a specific item in the virtual list regardless |
* of the physical items in the DOM tree. |
@@ -987,12 +1006,13 @@ |
Polymer.dom.flush(); |
- var firstVisible = this.firstVisibleIndex; |
idx = Math.min(Math.max(idx, 0), this._virtualCount-1); |
- |
- // start at the previous virtual item |
- // so we have a item above the first visible item |
- this._virtualStart = idx - 1; |
+ // update the virtual start only when needed |
+ if (!this._isIndexRendered(idx) || idx >= this._maxVirtualStart) { |
+ this._virtualStart = idx - 1; |
+ } |
+ // manage focus |
+ this._manageFocus(); |
// assign new models |
this._assignModels(); |
// measure the new sizes |
@@ -1055,7 +1075,7 @@ |
var key = this._collection.getKey(item); |
var pidx = this._physicalIndexForKey[key]; |
- if (pidx !== undefined) { |
+ if (pidx != null) { |
return this._physicalItems[pidx]._templateInstance; |
} |
return null; |
@@ -1193,140 +1213,180 @@ |
var key = this._collection.getKey(item); |
var pidx = this._physicalIndexForKey[key]; |
- if (pidx !== undefined) { |
+ if (pidx != null) { |
this._updateMetrics([pidx]); |
this._positionItems(); |
} |
}, |
+ /** |
+ * Creates a temporary backfill item in the rendered pool of physical items |
+ * to replace the main focused item. The focused item has tabIndex = 0 |
+ * and might be currently focused by the user. |
+ * |
+ * This dynamic replacement helps to preserve the focus state. |
+ */ |
+ _manageFocus: function() { |
+ var fidx = this._focusedIndex; |
+ |
+ if (fidx >= 0 && fidx < this._virtualCount) { |
+ // if it's a valid index, check if that index is rendered |
+ // in a physical item. |
+ if (this._isIndexRendered(fidx)) { |
+ this._restoreFocusedItem(); |
+ } else { |
+ this._createFocusBackfillItem(); |
+ } |
+ } else if (this._virtualCount > 0 && this._physicalCount > 0) { |
+ // otherwise, assign the initial focused index. |
+ this._focusedIndex = this._virtualStart; |
+ this._focusedItem = this._physicalItems[this._physicalStart]; |
+ } |
+ }, |
+ |
_isIndexRendered: function(idx) { |
return idx >= this._virtualStart && idx <= this._virtualEnd; |
}, |
- _getPhysicalItemForIndex: function(idx, force) { |
- if (!this._collection) { |
- return null; |
- } |
- if (!this._isIndexRendered(idx)) { |
- if (force) { |
- this.scrollToIndex(idx); |
- return this._getPhysicalItemForIndex(idx, false); |
- } |
- return null; |
- } |
- var item = this._getNormalizedItem(idx); |
- var physicalItem = this._physicalItems[this._physicalIndexForKey[this._collection.getKey(item)]]; |
+ _isIndexVisible: function(idx) { |
+ return idx >= this.firstVisibleIndex && idx <= this.lastVisibleIndex; |
+ }, |
- return physicalItem || null; |
+ _getPhysicalIndex: function(idx) { |
+ return this._physicalIndexForKey[this._collection.getKey(this._getNormalizedItem(idx))]; |
}, |
_focusPhysicalItem: function(idx) { |
- this._restoreFocusedItem(); |
- |
- var physicalItem = this._getPhysicalItemForIndex(idx, true); |
- if (!physicalItem) { |
+ if (idx < 0 || idx >= this._virtualCount) { |
return; |
} |
+ this._restoreFocusedItem(); |
+ // scroll to index to make sure it's rendered |
+ if (!this._isIndexRendered(idx)) { |
+ this.scrollToIndex(idx); |
+ } |
+ |
+ var physicalItem = this._physicalItems[this._getPhysicalIndex(idx)]; |
var SECRET = ~(Math.random() * 100); |
var model = physicalItem._templateInstance; |
var focusable; |
+ // set a secret tab index |
model.tabIndex = SECRET; |
- // the focusable element could be the entire physical item |
+ // check if focusable element is the physical item |
if (physicalItem.tabIndex === SECRET) { |
focusable = physicalItem; |
} |
- // the focusable element could be somewhere within the physical item |
+ // search for the element which tabindex is bound to the secret tab index |
if (!focusable) { |
focusable = Polymer.dom(physicalItem).querySelector('[tabindex="' + SECRET + '"]'); |
} |
// restore the tab index |
model.tabIndex = 0; |
+ // focus the focusable element |
+ this._focusedIndex = idx; |
focusable && focusable.focus(); |
}, |
- _restoreFocusedItem: function() { |
- if (!this._offscreenFocusedItem) { |
- return; |
- } |
- var item = this._getNormalizedItem(this._focusedIndex); |
- var pidx = this._physicalIndexForKey[this._collection.getKey(item)]; |
- |
- if (pidx !== undefined) { |
- this.translate3d(0, HIDDEN_Y, 0, this._physicalItems[pidx]); |
- this._physicalItems[pidx] = this._offscreenFocusedItem; |
- } |
- this._offscreenFocusedItem = null; |
- }, |
- |
_removeFocusedItem: function() { |
- if (!this._offscreenFocusedItem) { |
- return; |
+ if (this._offscreenFocusedItem) { |
+ Polymer.dom(this).removeChild(this._offscreenFocusedItem); |
} |
- Polymer.dom(this).removeChild(this._offscreenFocusedItem); |
this._offscreenFocusedItem = null; |
this._focusBackfillItem = null; |
+ this._focusedItem = null; |
+ this._focusedIndex = -1; |
}, |
_createFocusBackfillItem: function() { |
- if (this._offscreenFocusedItem) { |
+ var pidx, fidx = this._focusedIndex; |
+ if (this._offscreenFocusedItem || fidx < 0) { |
return; |
} |
- var item = this._getNormalizedItem(this._focusedIndex); |
- var pidx = this._physicalIndexForKey[this._collection.getKey(item)]; |
- |
- this._offscreenFocusedItem = this._physicalItems[pidx]; |
- this.translate3d(0, HIDDEN_Y, 0, this._offscreenFocusedItem); |
- |
if (!this._focusBackfillItem) { |
+ // create a physical item, so that it backfills the focused item. |
var stampedTemplate = this.stamp(null); |
this._focusBackfillItem = stampedTemplate.root.querySelector('*'); |
Polymer.dom(this).appendChild(stampedTemplate.root); |
} |
- this._physicalItems[pidx] = this._focusBackfillItem; |
+ // get the physical index for the focused index |
+ pidx = this._getPhysicalIndex(fidx); |
+ |
+ if (pidx != null) { |
+ // set the offcreen focused physical item |
+ this._offscreenFocusedItem = this._physicalItems[pidx]; |
+ // backfill the focused physical item |
+ this._physicalItems[pidx] = this._focusBackfillItem; |
+ // hide the focused physical |
+ this.translate3d(0, HIDDEN_Y, 0, this._offscreenFocusedItem); |
+ } |
+ }, |
+ |
+ _restoreFocusedItem: function() { |
+ var pidx, fidx = this._focusedIndex; |
+ |
+ if (!this._offscreenFocusedItem || this._focusedIndex < 0) { |
+ return; |
+ } |
+ // assign models to the focused index |
+ this._assignModels(); |
+ // get the new physical index for the focused index |
+ pidx = this._getPhysicalIndex(fidx); |
+ |
+ if (pidx != null) { |
+ // flip the focus backfill |
+ this._focusBackfillItem = this._physicalItems[pidx]; |
+ // restore the focused physical item |
+ this._physicalItems[pidx] = this._offscreenFocusedItem; |
+ // reset the offscreen focused item |
+ this._offscreenFocusedItem = null; |
+ // hide the physical item that backfills |
+ this.translate3d(0, HIDDEN_Y, 0, this._focusBackfillItem); |
+ } |
}, |
_didFocus: function(e) { |
var targetModel = this.modelForElement(e.target); |
+ var focusedModel = this._focusedItem ? this._focusedItem._templateInstance : null; |
+ var hasOffscreenFocusedItem = this._offscreenFocusedItem !== null; |
var fidx = this._focusedIndex; |
- if (!targetModel) { |
+ if (!targetModel || !focusedModel) { |
return; |
} |
- this._restoreFocusedItem(); |
- |
- if (this.modelForElement(this._offscreenFocusedItem) === targetModel) { |
- this.scrollToIndex(fidx); |
+ if (focusedModel === targetModel) { |
+ // if the user focused the same item, then bring it into view if it's not visible |
+ if (!this._isIndexVisible(fidx)) { |
+ this.scrollToIndex(fidx); |
+ } |
} else { |
+ this._restoreFocusedItem(); |
// restore tabIndex for the currently focused item |
- this._getModelFromItem(this._getNormalizedItem(fidx)).tabIndex = -1; |
+ focusedModel.tabIndex = -1; |
// set the tabIndex for the next focused item |
targetModel.tabIndex = 0; |
- fidx = /** @type {{index: number}} */(targetModel).index; |
+ fidx = targetModel[this.indexAs]; |
this._focusedIndex = fidx; |
- // bring the item into view |
- if (fidx < this.firstVisibleIndex || fidx > this.lastVisibleIndex) { |
- this.scrollToIndex(fidx); |
- } else { |
+ this._focusedItem = this._physicalItems[this._getPhysicalIndex(fidx)]; |
+ |
+ if (hasOffscreenFocusedItem && !this._offscreenFocusedItem) { |
this._update(); |
} |
} |
}, |
_didMoveUp: function() { |
- this._focusPhysicalItem(Math.max(0, this._focusedIndex - 1)); |
+ this._focusPhysicalItem(this._focusedIndex - 1); |
}, |
_didMoveDown: function() { |
- this._focusPhysicalItem(Math.min(this._virtualCount, this._focusedIndex + 1)); |
+ this._focusPhysicalItem(this._focusedIndex + 1); |
}, |
_didEnter: function(e) { |
- // focus the currently focused physical item |
this._focusPhysicalItem(this._focusedIndex); |
- // toggle selection |
- this._selectionHandler(/** @type {{keyboardEvent: Event}} */(e.detail).keyboardEvent); |
+ this._selectionHandler(e.detail.keyboardEvent); |
} |
}); |
-})(); |
+})(); |