| Index: lib/src/iron-list/iron-list.html
|
| diff --git a/lib/src/iron-list/iron-list.html b/lib/src/iron-list/iron-list.html
|
| index aaeed9b8337ddb1c867d253140ad355d0474586a..60539b9177be2a2263409e67cc11b0a6026a4277 100644
|
| --- a/lib/src/iron-list/iron-list.html
|
| +++ b/lib/src/iron-list/iron-list.html
|
| @@ -69,9 +69,19 @@ bound from the model object provided to the template scope):
|
| </iron-list>
|
| </template>
|
|
|
| +### Styling
|
| +
|
| +Use the `--iron-list-items-container` mixin to style the container of items, e.g.
|
| +
|
| + iron-list {
|
| + --iron-list-items-container: {
|
| + margin: auto;
|
| + };
|
| + }
|
| +
|
| ### Resizing
|
|
|
| -`iron-list` lays out the items when it recives a notification via the `resize` event.
|
| +`iron-list` lays out the items when it recives a notification via the `iron-resize` event.
|
| This event is fired by any element that implements `IronResizableBehavior`.
|
|
|
| By default, elements such as `iron-pages`, `paper-tabs` or `paper-dialog` will trigger
|
| @@ -79,46 +89,47 @@ this event automatically. If you hide the list manually (e.g. you use `display:
|
| you might want to implement `IronResizableBehavior` or fire this event manually right
|
| after the list became visible again. e.g.
|
|
|
| - document.querySelector('iron-list').fire('resize');
|
| + document.querySelector('iron-list').fire('iron-resize');
|
|
|
|
|
| @group Iron Element
|
| @element iron-list
|
| -@demo demo/index.html
|
| +@demo demo/index.html Simple list
|
| +@demo demo/selection.html Selection of items
|
| +@demo demo/collapse.html Collapsable items
|
| -->
|
|
|
| <dom-module id="iron-list">
|
| - <style>
|
| -
|
| - :host {
|
| - display: block;
|
| - }
|
| -
|
| - :host(.has-scroller) {
|
| - overflow: auto;
|
| - }
|
| + <template>
|
| + <style>
|
| + :host {
|
| + display: block;
|
| + }
|
|
|
| - :host(:not(.has-scroller)) {
|
| - position: relative;
|
| - }
|
| + :host(.has-scroller) {
|
| + overflow: auto;
|
| + }
|
|
|
| - #items {
|
| - position: relative;
|
| - }
|
| + :host(:not(.has-scroller)) {
|
| + position: relative;
|
| + }
|
|
|
| - #items > ::content > * {
|
| - width: 100%;
|
| - box-sizing: border-box;
|
| - position: absolute;
|
| - top: 0;
|
| - will-change: transform;
|
| - }
|
| + #items {
|
| + @apply(--iron-list-items-container);
|
| + position: relative;
|
| + }
|
|
|
| - </style>
|
| - <template>
|
| + #items > ::content > * {
|
| + width: 100%;
|
| + box-sizing: border-box;
|
| + position: absolute;
|
| + top: 0;
|
| + will-change: transform;
|
| + }
|
| + </style>
|
|
|
| <array-selector id="selector" items="{{items}}"
|
| - selected="{{selectedItems}}" selected-item="{{selectedItem}}">
|
| + selected="{{selectedItems}}" selected-item="{{selectedItem}}">
|
| </array-selector>
|
|
|
| <div id="items">
|
| @@ -162,8 +173,7 @@ after the list became visible again. e.g.
|
|
|
| /**
|
| * The name of the variable to add to the binding scope with the index
|
| - * for the row. If `sort` is provided, the index will reflect the
|
| - * sorted order (rather than the original array order).
|
| + * for the row.
|
| */
|
| indexAs: {
|
| type: String,
|
| @@ -242,6 +252,7 @@ after the list became visible again. e.g.
|
|
|
| /**
|
| * The element that controls the scroll
|
| + * @type {?Element}
|
| */
|
| _scroller: null,
|
|
|
| @@ -323,22 +334,26 @@ after the list became visible again. e.g.
|
|
|
| /**
|
| * An array of DOM nodes that are currently in the tree
|
| + * @type {?Array<!TemplatizerNode>}
|
| */
|
| _physicalItems: null,
|
|
|
| /**
|
| * An array of heights for each item in `_physicalItems`
|
| + * @type {?Array<number>}
|
| */
|
| _physicalSizes: null,
|
|
|
| /**
|
| * A cached value for the visible index.
|
| * See `firstVisibleIndex`
|
| + * @type {?number}
|
| */
|
| _firstVisibleIndexVal: null,
|
|
|
| /**
|
| * A Polymer collection for the items.
|
| + * @type {?Polymer.Collection}
|
| */
|
| _collection: null,
|
|
|
| @@ -356,6 +371,13 @@ after the list became visible again. e.g.
|
| },
|
|
|
| /**
|
| + * The bottom of the scroll.
|
| + */
|
| + get _scrollBottom() {
|
| + return this._scrollPosition + this._viewportSize;
|
| + },
|
| +
|
| + /**
|
| * The n-th item rendered in the last physical item.
|
| */
|
| get _virtualEnd() {
|
| @@ -371,8 +393,7 @@ after the list became visible again. e.g.
|
| * The largest n-th value for an item such that it can be rendered in `_physicalStart`.
|
| */
|
| get _maxVirtualStart() {
|
| - return this._virtualCount < this._physicalCount ?
|
| - this._virtualCount : this._virtualCount - this._physicalCount;
|
| + return Math.max(0, this._virtualCount - this._physicalCount);
|
| },
|
|
|
| /**
|
| @@ -425,9 +446,9 @@ after the list became visible again. e.g.
|
| },
|
|
|
| /**
|
| - * Gets the first visible item in the viewport.
|
| + * Gets the index of the first visible item in the viewport.
|
| *
|
| - * @property firstVisibleIndex
|
| + * @type {number}
|
| */
|
| get firstVisibleIndex() {
|
| var physicalOffset;
|
| @@ -466,8 +487,9 @@ after the list became visible again. e.g.
|
| // e.g. paper-scroll-header-panel
|
| var el = Polymer.dom(this);
|
|
|
| - if (el.parentNode && el.parentNode.scroller) {
|
| - this._scroller = el.parentNode.scroller;
|
| + var parentNode = /** @type {?{scroller: ?Element}} */ (el.parentNode);
|
| + if (parentNode && parentNode.scroller) {
|
| + this._scroller = parentNode.scroller;
|
| } else {
|
| this._scroller = this;
|
| this.classList.add('has-scroller');
|
| @@ -501,7 +523,7 @@ after the list became visible again. e.g.
|
| */
|
| updateViewportBoundaries: function() {
|
| var scrollerStyle = window.getComputedStyle(this._scroller);
|
| - this._scrollerPaddingTop = parseInt(scrollerStyle['padding-top']);
|
| + this._scrollerPaddingTop = parseInt(scrollerStyle['padding-top'], 10);
|
| this._viewportSize = this._scroller.offsetHeight;
|
| },
|
|
|
| @@ -510,19 +532,13 @@ after the list became visible again. e.g.
|
| * items in the viewport and recycle tiles as needed.
|
| */
|
| _refresh: function() {
|
| - var SCROLL_DIRECTION_UP = -1;
|
| - var SCROLL_DIRECTION_DOWN = 1;
|
| - var SCROLL_DIRECTION_NONE = 0;
|
| -
|
| // 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._scroller.scrollTop));
|
| -
|
| - var tileHeight, kth, recycledTileSet;
|
| + var tileHeight, tileTop, kth, recycledTileSet, scrollBottom;
|
| var ratio = this._ratio;
|
| var delta = scrollTop - this._scrollPosition;
|
| - var direction = SCROLL_DIRECTION_NONE;
|
| var recycledTiles = 0;
|
| var hiddenContentSize = this._hiddenContentSize;
|
| var currentRatio = ratio;
|
| @@ -534,18 +550,19 @@ after the list became visible again. e.g.
|
| // clear cached visible index
|
| this._firstVisibleIndexVal = null;
|
|
|
| + scrollBottom = this._scrollBottom;
|
| +
|
| // random access
|
| if (Math.abs(delta) > this._physicalSize) {
|
| this._physicalTop += delta;
|
| - direction = SCROLL_DIRECTION_NONE;
|
| recycledTiles = Math.round(delta / this._physicalAverage);
|
| }
|
| // scroll up
|
| else if (delta < 0) {
|
| var topSpace = scrollTop - this._physicalTop;
|
| var virtualStart = this._virtualStart;
|
| + var physicalBottom = this._physicalBottom;
|
|
|
| - direction = SCROLL_DIRECTION_UP;
|
| recycledTileSet = [];
|
|
|
| kth = this._physicalEnd;
|
| @@ -558,12 +575,14 @@ after the list became visible again. e.g.
|
| // recycle less physical items than the total
|
| recycledTiles < this._physicalCount &&
|
| // ensure that these recycled tiles are needed
|
| - virtualStart - recycledTiles > 0
|
| + virtualStart - recycledTiles > 0 &&
|
| + // ensure that the tile is not visible
|
| + physicalBottom - this._physicalSizes[kth] > scrollBottom
|
| ) {
|
|
|
| - tileHeight = this._physicalSizes[kth] || this._physicalAverage;
|
| + tileHeight = this._physicalSizes[kth];
|
| currentRatio += tileHeight / hiddenContentSize;
|
| -
|
| + physicalBottom -= tileHeight;
|
| recycledTileSet.push(kth);
|
| recycledTiles++;
|
| kth = (kth === 0) ? this._physicalCount - 1 : kth - 1;
|
| @@ -571,15 +590,13 @@ after the list became visible again. e.g.
|
|
|
| movingUp = recycledTileSet;
|
| recycledTiles = -recycledTiles;
|
| -
|
| }
|
| // scroll down
|
| else if (delta > 0) {
|
| - var bottomSpace = this._physicalBottom - (scrollTop + this._viewportSize);
|
| + var bottomSpace = this._physicalBottom - scrollBottom;
|
| var virtualEnd = this._virtualEnd;
|
| var lastVirtualItemIndex = this._virtualCount-1;
|
|
|
| - direction = SCROLL_DIRECTION_DOWN;
|
| recycledTileSet = [];
|
|
|
| kth = this._physicalStart;
|
| @@ -592,10 +609,12 @@ after the list became visible again. e.g.
|
| // recycle less physical items than the total
|
| recycledTiles < this._physicalCount &&
|
| // ensure that these recycled tiles are needed
|
| - virtualEnd + recycledTiles < lastVirtualItemIndex
|
| + virtualEnd + recycledTiles < lastVirtualItemIndex &&
|
| + // ensure that the tile is not visible
|
| + this._physicalTop + this._physicalSizes[kth] < scrollTop
|
| ) {
|
|
|
| - tileHeight = this._physicalSizes[kth] || this._physicalAverage;
|
| + tileHeight = this._physicalSizes[kth];
|
| currentRatio += tileHeight / hiddenContentSize;
|
|
|
| this._physicalTop += tileHeight;
|
| @@ -605,7 +624,15 @@ after the list became visible again. e.g.
|
| }
|
| }
|
|
|
| - if (recycledTiles !== 0) {
|
| + if (recycledTiles === 0) {
|
| + // If the list ever reach this case, the physical average is not significant enough
|
| + // to create all the items needed to cover the entire viewport.
|
| + // e.g. A few items have a height that differs from the average by serveral order of magnitude.
|
| + if (this._increasePoolIfNeeded()) {
|
| + // yield and set models to the new items
|
| + this.async(this._update);
|
| + }
|
| + } else {
|
| this._virtualStart = this._virtualStart + recycledTiles;
|
| this._update(recycledTileSet, movingUp);
|
| }
|
| @@ -613,14 +640,15 @@ after the list became visible again. e.g.
|
|
|
| /**
|
| * Update the list of items, starting from the `_virtualStartVal` item.
|
| + * @param {!Array<number>=} itemSet
|
| + * @param {!Array<number>=} movingUp
|
| */
|
| _update: function(itemSet, movingUp) {
|
| // update models
|
| this._assignModels(itemSet);
|
|
|
| // measure heights
|
| - // TODO(blasten) pass `recycledTileSet`
|
| - this._updateMetrics();
|
| + this._updateMetrics(itemSet);
|
|
|
| // adjust offset after measuring
|
| if (movingUp) {
|
| @@ -628,7 +656,6 @@ after the list became visible again. e.g.
|
| this._physicalTop -= this._physicalSizes[movingUp.pop()];
|
| }
|
| }
|
| -
|
| // update the position of the items
|
| this._positionItems();
|
|
|
| @@ -636,9 +663,9 @@ after the list became visible again. e.g.
|
| this._updateScrollerSize();
|
|
|
| // increase the pool of physical items if needed
|
| - if (itemSet = this._increasePoolIfNeeded()) {
|
| - // set models to the new items
|
| - this.async(this._update.bind(this, itemSet));
|
| + if (this._increasePoolIfNeeded()) {
|
| + // yield set models to the new items
|
| + this.async(this._update);
|
| }
|
| },
|
|
|
| @@ -663,24 +690,30 @@ after the list became visible again. e.g.
|
| },
|
|
|
| /**
|
| - * Increases the pool size. That is, the physical items in the DOM.
|
| + * Increases the pool of physical items only if needed.
|
| * This function will allocate additional physical items
|
| * (limited by `MAX_PHYSICAL_COUNT`) if the content size is shorter than
|
| * `_optPhysicalSize`
|
| *
|
| - * @return Array
|
| + * @return boolean
|
| */
|
| _increasePoolIfNeeded: function() {
|
| - if (this._physicalSize >= this._optPhysicalSize || this._physicalAverage === 0) {
|
| - return null;
|
| + if (this._physicalAverage === 0) {
|
| + return false;
|
| }
|
| + if (this._physicalBottom < this._scrollBottom || this._physicalTop > this._scrollPosition) {
|
| + return this._increasePool(1);
|
| + }
|
| + if (this._physicalSize < this._optPhysicalSize) {
|
| + return this._increasePool(Math.round((this._optPhysicalSize - this._physicalSize) * 1.2 / this._physicalAverage));
|
| + }
|
| + return false;
|
| + },
|
|
|
| - // the estimated number of physical items that we will need to reach
|
| - // the cap established by `_optPhysicalSize`.
|
| - var missingItems = Math.round(
|
| - (this._optPhysicalSize - this._physicalSize) * 1.2 / this._physicalAverage
|
| - );
|
| -
|
| + /**
|
| + * Increases the pool size.
|
| + */
|
| + _increasePool: function(missingItems) {
|
| // limit the size
|
| var nextPhysicalCount = Math.min(
|
| this._physicalCount + missingItems,
|
| @@ -692,23 +725,15 @@ after the list became visible again. e.g.
|
| var delta = nextPhysicalCount - prevPhysicalCount;
|
|
|
| if (delta <= 0) {
|
| - return null;
|
| + return false;
|
| }
|
|
|
| - var newPhysicalItems = this._createPool(delta);
|
| - var emptyArray = new Array(delta);
|
| -
|
| - [].push.apply(this._physicalItems, newPhysicalItems);
|
| - [].push.apply(this._physicalSizes, emptyArray);
|
| + [].push.apply(this._physicalItems, this._createPool(delta));
|
| + [].push.apply(this._physicalSizes, new Array(delta));
|
|
|
| this._physicalCount = prevPhysicalCount + delta;
|
|
|
| - // fill the array with the new item pos
|
| - while (delta > 0) {
|
| - emptyArray[--delta] = prevPhysicalCount + delta;
|
| - }
|
| -
|
| - return emptyArray;
|
| + return true;
|
| },
|
|
|
| /**
|
| @@ -858,6 +883,9 @@ after the list became visible again. e.g.
|
| }
|
| },
|
|
|
| + /**
|
| + * @param {!Array<!PolymerSplice>} splices
|
| + */
|
| _adjustVirtualIndex: function(splices) {
|
| var i, splice, idx;
|
|
|
| @@ -885,6 +913,9 @@ after the list became visible again. e.g.
|
| /**
|
| * Executes a provided function per every physical index in `itemSet`
|
| * `itemSet` default value is equivalent to the entire set of physical indexes.
|
| + *
|
| + * @param {!function(number, number)} fn
|
| + * @param {!Array<number>=} itemSet
|
| */
|
| _iterateItems: function(fn, itemSet) {
|
| var pidx, vidx, rtn, i;
|
| @@ -923,6 +954,7 @@ after the list became visible again. e.g.
|
|
|
| /**
|
| * Assigns the data models to a given set of items.
|
| + * @param {!Array<number>=} itemSet
|
| */
|
| _assignModels: function(itemSet) {
|
| this._iterateItems(function(pidx, vidx) {
|
| @@ -933,7 +965,8 @@ after the list became visible again. e.g.
|
| if (item) {
|
| inst[this.as] = item;
|
| inst.__key__ = this._collection.getKey(item);
|
| - inst[this.selectedAs] = this.$.selector.isSelected(item);
|
| + inst[this.selectedAs] =
|
| + /** @type {!ArraySelectorElement} */ (this.$.selector).isSelected(item);
|
| inst[this.indexAs] = vidx;
|
| el.removeAttribute('hidden');
|
| this._physicalIndexForKey[inst.__key__] = pidx;
|
| @@ -947,28 +980,32 @@ after the list became visible again. e.g.
|
|
|
| /**
|
| * Updates the height for a given set of items.
|
| + *
|
| + * @param {!Array<number>=} itemSet
|
| */
|
| - _updateMetrics: function() {
|
| - var total = 0;
|
| + _updateMetrics: function(itemSet) {
|
| + var newPhysicalSize = 0;
|
| + var oldPhysicalSize = 0;
|
| var prevAvgCount = this._physicalAverageCount;
|
| var prevPhysicalAvg = this._physicalAverage;
|
| -
|
| // Make sure we distributed all the physical items
|
| // so we can measure them
|
| Polymer.dom.flush();
|
|
|
| - for (var i = 0; i < this._physicalCount; i++) {
|
| - this._physicalSizes[i] = this._physicalItems[i].offsetHeight;
|
| - total += this._physicalSizes[i];
|
| - this._physicalAverageCount += this._physicalSizes[i] ? 1 : 0;
|
| - }
|
| + 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._physicalSize = total;
|
| + this._physicalSize = this._physicalSize + newPhysicalSize - oldPhysicalSize;
|
| this._viewportSize = this._scroller.offsetHeight;
|
|
|
| + // update the average if we measured something
|
| if (this._physicalAverageCount !== prevAvgCount) {
|
| this._physicalAverage = Math.round(
|
| - ((prevPhysicalAvg * prevAvgCount) + total) /
|
| + ((prevPhysicalAvg * prevAvgCount) + newPhysicalSize) /
|
| this._physicalAverageCount);
|
| }
|
| },
|
| @@ -976,7 +1013,7 @@ after the list became visible again. e.g.
|
| /**
|
| * Updates the position of the physical items.
|
| */
|
| - _positionItems: function(itemSet) {
|
| + _positionItems: function() {
|
| this._adjustScrollPosition();
|
|
|
| var y = this._physicalTop;
|
| @@ -986,7 +1023,7 @@ after the list became visible again. e.g.
|
| this.transform('translate3d(0, ' + y + 'px, 0)', this._physicalItems[pidx]);
|
| y += this._physicalSizes[pidx];
|
|
|
| - }, itemSet);
|
| + });
|
| },
|
|
|
| /**
|
| @@ -1018,6 +1055,8 @@ after the list became visible again. e.g.
|
|
|
| /**
|
| * Sets the scroll height, that's the height of the content,
|
| + *
|
| + * @param {boolean=} forceUpdate If true, updates the height no matter what.
|
| */
|
| _updateScrollerSize: function(forceUpdate) {
|
| this._estScrollHeight = (this._physicalBottom +
|
| @@ -1045,7 +1084,6 @@ after the list became visible again. e.g.
|
| return;
|
| }
|
|
|
| - var itemSet;
|
| var firstVisible = this.firstVisibleIndex;
|
|
|
| idx = Math.min(Math.max(idx, 0), this._virtualCount-1);
|
| @@ -1085,11 +1123,10 @@ after the list became visible again. e.g.
|
| this._resetScrollPosition(this._physicalTop + targetOffsetTop + 1);
|
|
|
| // increase the pool of physical items if needed
|
| - if (itemSet = this._increasePoolIfNeeded()) {
|
| - // set models to the new items
|
| - this.async(this._update.bind(this, itemSet));
|
| + if (this._increasePoolIfNeeded()) {
|
| + // yield set models to the new items
|
| + this.async(this._update);
|
| }
|
| -
|
| // clear cached visible index
|
| this._firstVisibleIndexVal = null;
|
| },
|
| @@ -1103,7 +1140,7 @@ after the list became visible again. e.g.
|
| },
|
|
|
| /**
|
| - * A handler for the `resize` event triggered by `IronResizableBehavior`
|
| + * A handler for the `iron-resize` event triggered by `IronResizableBehavior`
|
| * when the element is resized.
|
| */
|
| _resizeHandler: function() {
|
| @@ -1128,23 +1165,30 @@ after the list became visible again. e.g.
|
| },
|
|
|
| /**
|
| - * Select the list item at the given index.
|
| + * Gets a valid item instance from its index or the object value.
|
| *
|
| - * @method selectItem
|
| - * @param {(Object|number)} item the item object or its index
|
| + * @param {(Object|number)} item The item object or its index
|
| */
|
| - selectItem: function(item) {
|
| + _getNormalizedItem: function(item) {
|
| if (typeof item === 'number') {
|
| item = this.items[item];
|
| if (!item) {
|
| throw new RangeError('<item> not found');
|
| }
|
| - } else {
|
| - if (this._collection.getKey(item) === undefined) {
|
| - throw new TypeError('<item> should be a valid item');
|
| - }
|
| + } else if (this._collection.getKey(item) === undefined) {
|
| + throw new TypeError('<item> should be a valid item');
|
| }
|
| + return item;
|
| + },
|
|
|
| + /**
|
| + * Select the list item at the given index.
|
| + *
|
| + * @method selectItem
|
| + * @param {(Object|number)} item The item object or its index
|
| + */
|
| + selectItem: function(item) {
|
| + item = this._getNormalizedItem(item);
|
| var model = this._getModelFromItem(item);
|
|
|
| if (!this.multiSelection && this.selectedItem) {
|
| @@ -1159,21 +1203,12 @@ after the list became visible again. e.g.
|
| /**
|
| * Deselects the given item list if it is already selected.
|
| *
|
| +
|
| * @method deselect
|
| - * @param {(Object|number)} item the item object or its index
|
| + * @param {(Object|number)} item The item object or its index
|
| */
|
| deselectItem: function(item) {
|
| - if (typeof item === 'number') {
|
| - item = this.items[item];
|
| - if (!item) {
|
| - throw new RangeError('<item> not found');
|
| - }
|
| - } else {
|
| - if (this._collection.getKey(item) === undefined) {
|
| - throw new TypeError('<item> should be a valid item');
|
| - }
|
| - }
|
| -
|
| + item = this._getNormalizedItem(item);
|
| var model = this._getModelFromItem(item);
|
|
|
| if (model) {
|
| @@ -1187,11 +1222,11 @@ after the list became visible again. e.g.
|
| * has already been selected.
|
| *
|
| * @method toggleSelectionForItem
|
| - * @param {(Object|number)} item the item object or its index
|
| + * @param {(Object|number)} item The item object or its index
|
| */
|
| toggleSelectionForItem: function(item) {
|
| - var item = typeof item === 'number' ? this.items[item] : item;
|
| - if (this.$.selector.isSelected(item)) {
|
| + item = this._getNormalizedItem(item);
|
| + if (/** @type {!ArraySelectorElement} */ (this.$.selector).isSelected(item)) {
|
| this.deselectItem(item);
|
| } else {
|
| this.selectItem(item);
|
| @@ -1217,7 +1252,7 @@ after the list became visible again. e.g.
|
| unselect.call(this, this.selectedItem);
|
| }
|
|
|
| - this.$.selector.clearSelection();
|
| + /** @type {!ArraySelectorElement} */ (this.$.selector).clearSelection();
|
| },
|
|
|
| /**
|
| @@ -1227,8 +1262,10 @@ after the list became visible again. e.g.
|
| _selectionEnabledChanged: function(selectionEnabled) {
|
| if (selectionEnabled) {
|
| this.listen(this, 'tap', '_selectionHandler');
|
| + this.listen(this, 'keypress', '_selectionHandler');
|
| } else {
|
| this.unlisten(this, 'tap', '_selectionHandler');
|
| + this.unlisten(this, 'keypress', '_selectionHandler');
|
| }
|
| },
|
|
|
| @@ -1236,15 +1273,34 @@ after the list became visible again. e.g.
|
| * Select an item from an event object.
|
| */
|
| _selectionHandler: function(e) {
|
| - var model = this.modelForElement(e.target);
|
| - if (model) {
|
| - this.toggleSelectionForItem(model[this.as]);
|
| + if (e.type !== 'keypress' || e.keyCode === 13) {
|
| + var model = this.modelForElement(e.target);
|
| + if (model) {
|
| + this.toggleSelectionForItem(model[this.as]);
|
| + }
|
| }
|
| },
|
|
|
| _multiSelectionChanged: function(multiSelection) {
|
| this.clearSelection();
|
| this.$.selector.multi = multiSelection;
|
| + },
|
| +
|
| + /**
|
| + * Updates the size of an item.
|
| + *
|
| + * @method updateSizeForItem
|
| + * @param {(Object|number)} item The item object or its index
|
| + */
|
| + updateSizeForItem: function(item) {
|
| + item = this._getNormalizedItem(item);
|
| + var key = this._collection.getKey(item);
|
| + var pidx = this._physicalIndexForKey[key];
|
| +
|
| + if (pidx !== undefined) {
|
| + this._updateMetrics([pidx]);
|
| + this._positionItems();
|
| + }
|
| }
|
| });
|
|
|
|
|