| OLD | NEW |
| 1 (function() { | 1 (function() { |
| 2 | 2 |
| 3 var IOS = navigator.userAgent.match(/iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/); | 3 var IOS = navigator.userAgent.match(/iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/); |
| 4 var IOS_TOUCH_SCROLLING = IOS && IOS[1] >= 8; | 4 var IOS_TOUCH_SCROLLING = IOS && IOS[1] >= 8; |
| 5 var DEFAULT_PHYSICAL_COUNT = 3; | 5 var DEFAULT_PHYSICAL_COUNT = 3; |
| 6 var HIDDEN_Y = '-10000px'; | 6 var HIDDEN_Y = '-10000px'; |
| 7 var ITEM_WIDTH = 0; | 7 var ITEM_WIDTH = 0; |
| 8 var ITEM_HEIGHT = 1; | 8 var ITEM_HEIGHT = 1; |
| 9 var SECRET_TABINDEX = -100; | 9 var SECRET_TABINDEX = -100; |
| 10 | 10 |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 * | 549 * |
| 550 * @param {boolean} fromTop If the potential reusable items are above the sc
rolling region. | 550 * @param {boolean} fromTop If the potential reusable items are above the sc
rolling region. |
| 551 */ | 551 */ |
| 552 _getReusables: function(fromTop) { | 552 _getReusables: function(fromTop) { |
| 553 var ith, lastIth, offsetContent, physicalItemHeight; | 553 var ith, lastIth, offsetContent, physicalItemHeight; |
| 554 var idxs = []; | 554 var idxs = []; |
| 555 var protectedOffsetContent = this._hiddenContentSize * this._ratio; | 555 var protectedOffsetContent = this._hiddenContentSize * this._ratio; |
| 556 var virtualStart = this._virtualStart; | 556 var virtualStart = this._virtualStart; |
| 557 var virtualEnd = this._virtualEnd; | 557 var virtualEnd = this._virtualEnd; |
| 558 var physicalCount = this._physicalCount; | 558 var physicalCount = this._physicalCount; |
| 559 var physicalTop = this._physicalTop; | 559 var physicalTop = this._physicalTop + this._scrollerPaddingTop; |
| 560 var scrollTop = this._scrollTop; | 560 var scrollTop = this._scrollTop; |
| 561 var scrollBottom = this._scrollBottom; | 561 var scrollBottom = this._scrollBottom; |
| 562 | 562 |
| 563 if (fromTop) { | 563 if (fromTop) { |
| 564 ith = this._physicalStart; | 564 ith = this._physicalStart; |
| 565 lastIth = this._physicalEnd; | 565 lastIth = this._physicalEnd; |
| 566 offsetContent = scrollTop - physicalTop; | 566 offsetContent = scrollTop - physicalTop; |
| 567 } else { | 567 } else { |
| 568 ith = this._physicalEnd; | 568 ith = this._physicalEnd; |
| 569 lastIth = this._physicalStart; | 569 lastIth = this._physicalStart; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 594 } | 594 } |
| 595 // Check that the index is not visible. | 595 // Check that the index is not visible. |
| 596 if (physicalTop + this._physicalSize - physicalItemHeight <= scrollBot
tom) { | 596 if (physicalTop + this._physicalSize - physicalItemHeight <= scrollBot
tom) { |
| 597 break; | 597 break; |
| 598 } | 598 } |
| 599 idxs.push(ith); | 599 idxs.push(ith); |
| 600 physicalTop = physicalTop - physicalItemHeight; | 600 physicalTop = physicalTop - physicalItemHeight; |
| 601 ith = (ith === 0) ? physicalCount - 1 : ith - 1; | 601 ith = (ith === 0) ? physicalCount - 1 : ith - 1; |
| 602 } | 602 } |
| 603 } | 603 } |
| 604 return { indexes: idxs, physicalTop: physicalTop }; | 604 return { indexes: idxs, physicalTop: physicalTop - this._scrollerPaddingTo
p }; |
| 605 }, | 605 }, |
| 606 | 606 |
| 607 /** | 607 /** |
| 608 * Update the list of items, starting from the `_virtualStart` item. | 608 * Update the list of items, starting from the `_virtualStart` item. |
| 609 * @param {!Array<number>=} itemSet | 609 * @param {!Array<number>=} itemSet |
| 610 * @param {!Array<number>=} movingUp | 610 * @param {!Array<number>=} movingUp |
| 611 */ | 611 */ |
| 612 _update: function(itemSet, movingUp) { | 612 _update: function(itemSet, movingUp) { |
| 613 if (itemSet && itemSet.length === 0) { | 613 if (itemSet && itemSet.length === 0) { |
| 614 return; | 614 return; |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 var oldPhysicalSize = 0; | 997 var oldPhysicalSize = 0; |
| 998 var prevAvgCount = this._physicalAverageCount; | 998 var prevAvgCount = this._physicalAverageCount; |
| 999 var prevPhysicalAvg = this._physicalAverage; | 999 var prevPhysicalAvg = this._physicalAverage; |
| 1000 | 1000 |
| 1001 this._iterateItems(function(pidx, vidx) { | 1001 this._iterateItems(function(pidx, vidx) { |
| 1002 oldPhysicalSize += this._physicalSizes[pidx] || 0; | 1002 oldPhysicalSize += this._physicalSizes[pidx] || 0; |
| 1003 this._physicalSizes[pidx] = this._physicalItems[pidx].offsetHeight; | 1003 this._physicalSizes[pidx] = this._physicalItems[pidx].offsetHeight; |
| 1004 newPhysicalSize += this._physicalSizes[pidx]; | 1004 newPhysicalSize += this._physicalSizes[pidx]; |
| 1005 this._physicalAverageCount += this._physicalSizes[pidx] ? 1 : 0; | 1005 this._physicalAverageCount += this._physicalSizes[pidx] ? 1 : 0; |
| 1006 }, itemSet); | 1006 }, itemSet); |
| 1007 | 1007 |
| 1008 if (this.grid) { | 1008 if (this.grid) { |
| 1009 this._updateGridMetrics(); | 1009 this._updateGridMetrics(); |
| 1010 this._physicalSize = Math.ceil(this._physicalCount / this._itemsPerRow)
* this._rowHeight; | 1010 this._physicalSize = Math.ceil(this._physicalCount / this._itemsPerRow)
* this._rowHeight; |
| 1011 } else { | 1011 } else { |
| 1012 this._physicalSize = this._physicalSize + newPhysicalSize - oldPhysicalS
ize; | 1012 this._physicalSize = this._physicalSize + newPhysicalSize - oldPhysicalS
ize; |
| 1013 } | 1013 } |
| 1014 // Update the average if it measured something. | 1014 // Update the average if it measured something. |
| 1015 if (this._physicalAverageCount !== prevAvgCount) { | 1015 if (this._physicalAverageCount !== prevAvgCount) { |
| 1016 this._physicalAverage = Math.round( | 1016 this._physicalAverage = Math.round( |
| 1017 ((prevPhysicalAvg * prevAvgCount) + newPhysicalSize) / | 1017 ((prevPhysicalAvg * prevAvgCount) + newPhysicalSize) / |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1190 this._physicalAverage = 0; | 1190 this._physicalAverage = 0; |
| 1191 this._physicalAverageCount = 0; | 1191 this._physicalAverageCount = 0; |
| 1192 }, | 1192 }, |
| 1193 | 1193 |
| 1194 /** | 1194 /** |
| 1195 * A handler for the `iron-resize` event triggered by `IronResizableBehavior
` | 1195 * A handler for the `iron-resize` event triggered by `IronResizableBehavior
` |
| 1196 * when the element is resized. | 1196 * when the element is resized. |
| 1197 */ | 1197 */ |
| 1198 _resizeHandler: function() { | 1198 _resizeHandler: function() { |
| 1199 // iOS fires the resize event when the address bar slides up | 1199 // iOS fires the resize event when the address bar slides up |
| 1200 if (IOS && Math.abs(this._viewportHeight - this._scrollTargetHeight) < 100
) { | 1200 var delta = Math.abs(this._viewportHeight - this._scrollTargetHeight); |
| 1201 if (IOS && delta > 0 && delta < 100) { |
| 1201 return; | 1202 return; |
| 1202 } | 1203 } |
| 1203 // In Desktop Safari 9.0.3, if the scroll bars are always shown, | 1204 // In Desktop Safari 9.0.3, if the scroll bars are always shown, |
| 1204 // changing the scroll position from a resize handler would result in | 1205 // changing the scroll position from a resize handler would result in |
| 1205 // the scroll position being reset. Waiting 1ms fixes the issue. | 1206 // the scroll position being reset. Waiting 1ms fixes the issue. |
| 1206 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', function() { | 1207 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', function() { |
| 1207 this.updateViewportBoundaries(); | 1208 this.updateViewportBoundaries(); |
| 1208 this._render(); | 1209 this._render(); |
| 1209 if (this._isVisible) { | 1210 if (this._isVisible) { |
| 1210 this.toggleScrollListener(true); | 1211 this.toggleScrollListener(true); |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1457 if (this._offscreenFocusedItem) { | 1458 if (this._offscreenFocusedItem) { |
| 1458 Polymer.dom(this).removeChild(this._offscreenFocusedItem); | 1459 Polymer.dom(this).removeChild(this._offscreenFocusedItem); |
| 1459 } | 1460 } |
| 1460 this._offscreenFocusedItem = null; | 1461 this._offscreenFocusedItem = null; |
| 1461 this._focusBackfillItem = null; | 1462 this._focusBackfillItem = null; |
| 1462 this._focusedItem = null; | 1463 this._focusedItem = null; |
| 1463 this._focusedIndex = -1; | 1464 this._focusedIndex = -1; |
| 1464 }, | 1465 }, |
| 1465 | 1466 |
| 1466 _createFocusBackfillItem: function() { | 1467 _createFocusBackfillItem: function() { |
| 1467 var pidx, fidx = this._focusedIndex; | 1468 var fidx = this._focusedIndex; |
| 1468 if (this._offscreenFocusedItem || fidx < 0) { | 1469 var pidx = this._getPhysicalIndex(fidx); |
| 1470 |
| 1471 if (this._offscreenFocusedItem || pidx == null || fidx < 0) { |
| 1469 return; | 1472 return; |
| 1470 } | 1473 } |
| 1471 if (!this._focusBackfillItem) { | 1474 if (!this._focusBackfillItem) { |
| 1472 // create a physical item, so that it backfills the focused item. | 1475 // Create a physical item. |
| 1473 var stampedTemplate = this.stamp(null); | 1476 var stampedTemplate = this.stamp(null); |
| 1474 this._focusBackfillItem = stampedTemplate.root.querySelector('*'); | 1477 this._focusBackfillItem = stampedTemplate.root.querySelector('*'); |
| 1475 Polymer.dom(this).appendChild(stampedTemplate.root); | 1478 Polymer.dom(this).appendChild(stampedTemplate.root); |
| 1476 } | 1479 } |
| 1477 // get the physical index for the focused index | 1480 // Set the offcreen focused physical item. |
| 1478 pidx = this._getPhysicalIndex(fidx); | 1481 this._offscreenFocusedItem = this._physicalItems[pidx]; |
| 1479 | 1482 this._offscreenFocusedItem._templateInstance.tabIndex = 0; |
| 1480 if (pidx != null) { | 1483 this._physicalItems[pidx] = this._focusBackfillItem; |
| 1481 // set the offcreen focused physical item | 1484 // Hide the focused physical. |
| 1482 this._offscreenFocusedItem = this._physicalItems[pidx]; | 1485 this.translate3d(0, HIDDEN_Y, 0, this._offscreenFocusedItem); |
| 1483 // backfill the focused physical item | |
| 1484 this._physicalItems[pidx] = this._focusBackfillItem; | |
| 1485 // hide the focused physical | |
| 1486 this.translate3d(0, HIDDEN_Y, 0, this._offscreenFocusedItem); | |
| 1487 } | |
| 1488 }, | 1486 }, |
| 1489 | 1487 |
| 1490 _restoreFocusedItem: function() { | 1488 _restoreFocusedItem: function() { |
| 1491 var pidx, fidx = this._focusedIndex; | 1489 var pidx, fidx = this._focusedIndex; |
| 1492 | 1490 |
| 1493 if (!this._offscreenFocusedItem || this._focusedIndex < 0) { | 1491 if (!this._offscreenFocusedItem || this._focusedIndex < 0) { |
| 1494 return; | 1492 return; |
| 1495 } | 1493 } |
| 1496 // assign models to the focused index | 1494 // Assign models to the focused index. |
| 1497 this._assignModels(); | 1495 this._assignModels(); |
| 1498 // get the new physical index for the focused index | 1496 // Get the new physical index for the focused index. |
| 1499 pidx = this._getPhysicalIndex(fidx); | 1497 pidx = this._getPhysicalIndex(fidx); |
| 1500 | 1498 |
| 1501 if (pidx != null) { | 1499 if (pidx != null) { |
| 1502 // flip the focus backfill | 1500 // Flip the focus backfill. |
| 1503 this._focusBackfillItem = this._physicalItems[pidx]; | 1501 this._focusBackfillItem = this._physicalItems[pidx]; |
| 1504 // restore the focused physical item | 1502 this._focusBackfillItem._templateInstance.tabIndex = -1; |
| 1503 // Restore the focused physical item. |
| 1505 this._physicalItems[pidx] = this._offscreenFocusedItem; | 1504 this._physicalItems[pidx] = this._offscreenFocusedItem; |
| 1506 // reset the offscreen focused item | 1505 // Reset the offscreen focused item. |
| 1507 this._offscreenFocusedItem = null; | 1506 this._offscreenFocusedItem = null; |
| 1508 // hide the physical item that backfills | 1507 // Hide the physical item that backfills. |
| 1509 this.translate3d(0, HIDDEN_Y, 0, this._focusBackfillItem); | 1508 this.translate3d(0, HIDDEN_Y, 0, this._focusBackfillItem); |
| 1510 } | 1509 } |
| 1511 }, | 1510 }, |
| 1512 | 1511 |
| 1513 _didFocus: function(e) { | 1512 _didFocus: function(e) { |
| 1514 var targetModel = this.modelForElement(e.target); | 1513 var targetModel = this.modelForElement(e.target); |
| 1515 var focusedModel = this._focusedItem ? this._focusedItem._templateInstance
: null; | 1514 var focusedModel = this._focusedItem ? this._focusedItem._templateInstance
: null; |
| 1516 var hasOffscreenFocusedItem = this._offscreenFocusedItem !== null; | 1515 var hasOffscreenFocusedItem = this._offscreenFocusedItem !== null; |
| 1517 var fidx = this._focusedIndex; | 1516 var fidx = this._focusedIndex; |
| 1518 | 1517 |
| 1519 if (!targetModel || !focusedModel) { | 1518 if (!targetModel || !focusedModel) { |
| 1520 return; | 1519 return; |
| 1521 } | 1520 } |
| 1522 if (focusedModel === targetModel) { | 1521 if (focusedModel === targetModel) { |
| 1523 // if the user focused the same item, then bring it into view if it's no
t visible | 1522 // if the user focused the same item, then bring it into view if it's no
t visible |
| 1524 if (!this._isIndexVisible(fidx)) { | 1523 if (!this._isIndexVisible(fidx)) { |
| 1525 this.scrollToIndex(fidx); | 1524 this.scrollToIndex(fidx); |
| 1526 } | 1525 } |
| 1527 } else { | 1526 } else { |
| 1528 this._restoreFocusedItem(); | 1527 this._restoreFocusedItem(); |
| 1529 // restore tabIndex for the currently focused item | 1528 // restore tabIndex for the currently focused item |
| 1530 focusedModel.tabIndex = -1; | 1529 focusedModel.tabIndex = -1; |
| 1531 // set the tabIndex for the next focused item | 1530 // set the tabIndex for the next focused item |
| 1532 targetModel.tabIndex = 0; | 1531 targetModel.tabIndex = 0; |
| 1533 fidx = targetModel[this.indexAs]; | 1532 fidx = targetModel[this.indexAs]; |
| 1534 this._focusedIndex = fidx; | 1533 this._focusedIndex = fidx; |
| 1535 this._focusedItem = this._physicalItems[this._getPhysicalIndex(fidx)]; | 1534 this._focusedItem = this._physicalItems[this._getPhysicalIndex(fidx)]; |
| 1536 | |
| 1537 if (hasOffscreenFocusedItem && !this._offscreenFocusedItem) { | 1535 if (hasOffscreenFocusedItem && !this._offscreenFocusedItem) { |
| 1538 this._update(); | 1536 this._update(); |
| 1539 } | 1537 } |
| 1540 } | 1538 } |
| 1541 }, | 1539 }, |
| 1542 | 1540 |
| 1543 _didMoveUp: function() { | 1541 _didMoveUp: function() { |
| 1544 this._focusPhysicalItem(this._focusedIndex - 1); | 1542 this._focusPhysicalItem(this._focusedIndex - 1); |
| 1545 }, | 1543 }, |
| 1546 | 1544 |
| 1547 _didMoveDown: function(e) { | 1545 _didMoveDown: function(e) { |
| 1548 // disable scroll when pressing the down key | 1546 // disable scroll when pressing the down key |
| 1549 e.detail.keyboardEvent.preventDefault(); | 1547 e.detail.keyboardEvent.preventDefault(); |
| 1550 this._focusPhysicalItem(this._focusedIndex + 1); | 1548 this._focusPhysicalItem(this._focusedIndex + 1); |
| 1551 }, | 1549 }, |
| 1552 | 1550 |
| 1553 _didEnter: function(e) { | 1551 _didEnter: function(e) { |
| 1554 this._focusPhysicalItem(this._focusedIndex); | 1552 this._focusPhysicalItem(this._focusedIndex); |
| 1555 this._selectionHandler(e.detail.keyboardEvent); | 1553 this._selectionHandler(e.detail.keyboardEvent); |
| 1556 } | 1554 } |
| 1557 }); | 1555 }); |
| 1558 | 1556 |
| 1559 })(); | 1557 })(); |
| OLD | NEW |