| 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 MAX_PHYSICAL_COUNT = 500; | |
| 7 var HIDDEN_Y = '-10000px'; | 6 var HIDDEN_Y = '-10000px'; |
| 7 var DEFAULT_GRID_SIZE = 200; |
| 8 | 8 |
| 9 Polymer({ | 9 Polymer({ |
| 10 | 10 |
| 11 is: 'iron-list', | 11 is: 'iron-list', |
| 12 | 12 |
| 13 properties: { | 13 properties: { |
| 14 | 14 |
| 15 /** | 15 /** |
| 16 * An array containing items determining how many instances of the templat
e | 16 * An array containing items determining how many instances of the templat
e |
| 17 * to stamp and that that each template instance should bind to. | 17 * to stamp and that that each template instance should bind to. |
| 18 */ | 18 */ |
| 19 items: { | 19 items: { |
| 20 type: Array | 20 type: Array |
| 21 }, | 21 }, |
| 22 | 22 |
| 23 /** | 23 /** |
| 24 * The max count of physical items the pool can extend to. |
| 25 */ |
| 26 maxPhysicalCount: { |
| 27 type: Number, |
| 28 value: 500 |
| 29 }, |
| 30 |
| 31 /** |
| 24 * The name of the variable to add to the binding scope for the array | 32 * The name of the variable to add to the binding scope for the array |
| 25 * element associated with a given template instance. | 33 * element associated with a given template instance. |
| 26 */ | 34 */ |
| 27 as: { | 35 as: { |
| 28 type: String, | 36 type: String, |
| 29 value: 'item' | 37 value: 'item' |
| 30 }, | 38 }, |
| 31 | 39 |
| 32 /** | 40 /** |
| 33 * The name of the variable to add to the binding scope with the index | 41 * The name of the variable to add to the binding scope with the index |
| 34 * for the row. | 42 * for the row. |
| 35 */ | 43 */ |
| 36 indexAs: { | 44 indexAs: { |
| 37 type: String, | 45 type: String, |
| 38 value: 'index' | 46 value: 'index' |
| 39 }, | 47 }, |
| 40 | 48 |
| 41 /** | 49 /** |
| 42 * The name of the variable to add to the binding scope to indicate | 50 * The name of the variable to add to the binding scope to indicate |
| 43 * if the row is selected. | 51 * if the row is selected. |
| 44 */ | 52 */ |
| 45 selectedAs: { | 53 selectedAs: { |
| 46 type: String, | 54 type: String, |
| 47 value: 'selected' | 55 value: 'selected' |
| 48 }, | 56 }, |
| 49 | 57 |
| 50 /** | 58 /** |
| 59 * When true, the list is rendered as a grid. Grid items must have |
| 60 * fixed width and height set via CSS. e.g. |
| 61 * |
| 62 * ```html |
| 63 * <iron-list grid> |
| 64 * <template> |
| 65 * <div style="width: 100px; height: 100px;"> 100x100 </div> |
| 66 * </template> |
| 67 * </iron-list> |
| 68 * ``` |
| 69 */ |
| 70 grid: { |
| 71 type: Boolean, |
| 72 value: false, |
| 73 reflectToAttribute: true |
| 74 }, |
| 75 |
| 76 /** |
| 51 * When true, tapping a row will select the item, placing its data model | 77 * When true, tapping a row will select the item, placing its data model |
| 52 * in the set of selected items retrievable via the selection property. | 78 * in the set of selected items retrievable via the selection property. |
| 53 * | 79 * |
| 54 * Note that tapping focusable elements within the list item will not | 80 * Note that tapping focusable elements within the list item will not |
| 55 * result in selection, since they are presumed to have their * own action
. | 81 * result in selection, since they are presumed to have their * own action
. |
| 56 */ | 82 */ |
| 57 selectionEnabled: { | 83 selectionEnabled: { |
| 58 type: Boolean, | 84 type: Boolean, |
| 59 value: false | 85 value: false |
| 60 }, | 86 }, |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 _estScrollHeight: 0, | 186 _estScrollHeight: 0, |
| 161 | 187 |
| 162 /** | 188 /** |
| 163 * The scroll height of the dom node | 189 * The scroll height of the dom node |
| 164 */ | 190 */ |
| 165 _scrollHeight: 0, | 191 _scrollHeight: 0, |
| 166 | 192 |
| 167 /** | 193 /** |
| 168 * The height of the list. This is referred as the viewport in the context o
f list. | 194 * The height of the list. This is referred as the viewport in the context o
f list. |
| 169 */ | 195 */ |
| 170 _viewportSize: 0, | 196 _viewportHeight: 0, |
| 197 |
| 198 /** |
| 199 * The width of the list. This is referred as the viewport in the context of
list. |
| 200 */ |
| 201 _viewportWidth: 0, |
| 171 | 202 |
| 172 /** | 203 /** |
| 173 * An array of DOM nodes that are currently in the tree | 204 * An array of DOM nodes that are currently in the tree |
| 174 * @type {?Array<!TemplatizerNode>} | 205 * @type {?Array<!TemplatizerNode>} |
| 175 */ | 206 */ |
| 176 _physicalItems: null, | 207 _physicalItems: null, |
| 177 | 208 |
| 178 /** | 209 /** |
| 179 * An array of heights for each item in `_physicalItems` | 210 * An array of heights for each item in `_physicalItems` |
| 180 * @type {?Array<number>} | 211 * @type {?Array<number>} |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 */ | 264 */ |
| 234 _offscreenFocusedItem: null, | 265 _offscreenFocusedItem: null, |
| 235 | 266 |
| 236 /** | 267 /** |
| 237 * The item that backfills the `_offscreenFocusedItem` in the physical items | 268 * The item that backfills the `_offscreenFocusedItem` in the physical items |
| 238 * list when that item is moved offscreen. | 269 * list when that item is moved offscreen. |
| 239 */ | 270 */ |
| 240 _focusBackfillItem: null, | 271 _focusBackfillItem: null, |
| 241 | 272 |
| 242 /** | 273 /** |
| 274 * The maximum items per row |
| 275 */ |
| 276 _itemsPerRow: 1, |
| 277 |
| 278 /** |
| 279 * The width of each grid item |
| 280 */ |
| 281 _itemWidth: 0, |
| 282 |
| 283 /** |
| 284 * The height of the row in grid layout. |
| 285 */ |
| 286 _rowHeight: 0, |
| 287 |
| 288 /** |
| 243 * The bottom of the physical content. | 289 * The bottom of the physical content. |
| 244 */ | 290 */ |
| 245 get _physicalBottom() { | 291 get _physicalBottom() { |
| 246 return this._physicalTop + this._physicalSize; | 292 return this._physicalTop + this._physicalSize; |
| 247 }, | 293 }, |
| 248 | 294 |
| 249 /** | 295 /** |
| 250 * The bottom of the scroll. | 296 * The bottom of the scroll. |
| 251 */ | 297 */ |
| 252 get _scrollBottom() { | 298 get _scrollBottom() { |
| 253 return this._scrollPosition + this._viewportSize; | 299 return this._scrollPosition + this._viewportHeight; |
| 254 }, | 300 }, |
| 255 | 301 |
| 256 /** | 302 /** |
| 257 * The n-th item rendered in the last physical item. | 303 * The n-th item rendered in the last physical item. |
| 258 */ | 304 */ |
| 259 get _virtualEnd() { | 305 get _virtualEnd() { |
| 260 return this._virtualStart + this._physicalCount - 1; | 306 return this._virtualStart + this._physicalCount - 1; |
| 261 }, | 307 }, |
| 262 | 308 |
| 263 /** | 309 /** |
| 264 * The height of the physical content that isn't on the screen. | 310 * The height of the physical content that isn't on the screen. |
| 265 */ | 311 */ |
| 266 get _hiddenContentSize() { | 312 get _hiddenContentSize() { |
| 267 return this._physicalSize - this._viewportSize; | 313 var size = this.grid ? this._physicalRows * this._rowHeight : this._physic
alSize; |
| 314 return size - this._viewportHeight; |
| 268 }, | 315 }, |
| 269 | 316 |
| 270 /** | 317 /** |
| 271 * The maximum scroll top value. | 318 * The maximum scroll top value. |
| 272 */ | 319 */ |
| 273 get _maxScrollTop() { | 320 get _maxScrollTop() { |
| 274 return this._estScrollHeight - this._viewportSize + this._scrollerPaddingT
op; | 321 return this._estScrollHeight - this._viewportHeight + this._scrollerPaddin
gTop; |
| 275 }, | 322 }, |
| 276 | 323 |
| 277 /** | 324 /** |
| 278 * The lowest n-th value for an item such that it can be rendered in `_physi
calStart`. | 325 * The lowest n-th value for an item such that it can be rendered in `_physi
calStart`. |
| 279 */ | 326 */ |
| 280 _minVirtualStart: 0, | 327 _minVirtualStart: 0, |
| 281 | 328 |
| 282 /** | 329 /** |
| 283 * The largest n-th value for an item such that it can be rendered in `_phys
icalStart`. | 330 * The largest n-th value for an item such that it can be rendered in `_phys
icalStart`. |
| 284 */ | 331 */ |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 _physicalEnd: 0, | 383 _physicalEnd: 0, |
| 337 | 384 |
| 338 /** | 385 /** |
| 339 * An optimal physical size such that we will have enough physical items | 386 * An optimal physical size such that we will have enough physical items |
| 340 * to fill up the viewport and recycle when the user scrolls. | 387 * to fill up the viewport and recycle when the user scrolls. |
| 341 * | 388 * |
| 342 * This default value assumes that we will at least have the equivalent | 389 * This default value assumes that we will at least have the equivalent |
| 343 * to a viewport of physical items above and below the user's viewport. | 390 * to a viewport of physical items above and below the user's viewport. |
| 344 */ | 391 */ |
| 345 get _optPhysicalSize() { | 392 get _optPhysicalSize() { |
| 346 return this._viewportSize * this._maxPages; | 393 if (this.grid) { |
| 394 return this._estRowsInView * this._rowHeight * this._maxPages; |
| 395 } |
| 396 return this._viewportHeight * this._maxPages; |
| 397 }, |
| 398 |
| 399 get _optPhysicalCount() { |
| 400 return this._estRowsInView * this._itemsPerRow * this._maxPages; |
| 347 }, | 401 }, |
| 348 | 402 |
| 349 /** | 403 /** |
| 350 * True if the current list is visible. | 404 * True if the current list is visible. |
| 351 */ | 405 */ |
| 352 get _isVisible() { | 406 get _isVisible() { |
| 353 return this.scrollTarget && Boolean(this.scrollTarget.offsetWidth || this.
scrollTarget.offsetHeight); | 407 return this.scrollTarget && Boolean(this.scrollTarget.offsetWidth || this.
scrollTarget.offsetHeight); |
| 354 }, | 408 }, |
| 355 | 409 |
| 356 /** | 410 /** |
| 357 * Gets the index of the first visible item in the viewport. | 411 * Gets the index of the first visible item in the viewport. |
| 358 * | 412 * |
| 359 * @type {number} | 413 * @type {number} |
| 360 */ | 414 */ |
| 361 get firstVisibleIndex() { | 415 get firstVisibleIndex() { |
| 362 if (this._firstVisibleIndexVal === null) { | 416 if (this._firstVisibleIndexVal === null) { |
| 363 var physicalOffset = this._physicalTop + this._scrollerPaddingTop; | 417 var physicalOffset = Math.floor(this._physicalTop + this._scrollerPaddin
gTop); |
| 364 | 418 |
| 365 this._firstVisibleIndexVal = this._iterateItems( | 419 this._firstVisibleIndexVal = this._iterateItems( |
| 366 function(pidx, vidx) { | 420 function(pidx, vidx) { |
| 367 physicalOffset += this._physicalSizes[pidx]; | 421 physicalOffset += this._getPhysicalSizeIncrement(pidx); |
| 422 |
| 368 if (physicalOffset > this._scrollPosition) { | 423 if (physicalOffset > this._scrollPosition) { |
| 369 return vidx; | 424 return this.grid ? vidx - (vidx % this._itemsPerRow) : vidx; |
| 425 } |
| 426 |
| 427 // Handle a partially rendered final row in grid mode |
| 428 if (this.grid && this._virtualCount - 1 === vidx) { |
| 429 return vidx - (vidx % this._itemsPerRow); |
| 370 } | 430 } |
| 371 }) || 0; | 431 }) || 0; |
| 372 } | 432 } |
| 373 return this._firstVisibleIndexVal; | 433 return this._firstVisibleIndexVal; |
| 374 }, | 434 }, |
| 375 | 435 |
| 376 /** | 436 /** |
| 377 * Gets the index of the last visible item in the viewport. | 437 * Gets the index of the last visible item in the viewport. |
| 378 * | 438 * |
| 379 * @type {number} | 439 * @type {number} |
| 380 */ | 440 */ |
| 381 get lastVisibleIndex() { | 441 get lastVisibleIndex() { |
| 382 if (this._lastVisibleIndexVal === null) { | 442 if (this._lastVisibleIndexVal === null) { |
| 383 var physicalOffset = this._physicalTop; | 443 if (this.grid) { |
| 444 var lastIndex = this.firstVisibleIndex + this._estRowsInView * this._i
temsPerRow - 1; |
| 445 this._lastVisibleIndexVal = lastIndex > this._virtualCount ? this._vir
tualCount : lastIndex; |
| 446 } else { |
| 447 var physicalOffset = this._physicalTop; |
| 384 | 448 |
| 385 this._iterateItems(function(pidx, vidx) { | 449 this._iterateItems(function(pidx, vidx) { |
| 386 physicalOffset += this._physicalSizes[pidx]; | 450 physicalOffset += this._getPhysicalSizeIncrement(pidx); |
| 387 | 451 |
| 388 if (physicalOffset <= this._scrollBottom) { | 452 if(physicalOffset <= this._scrollBottom) { |
| 389 this._lastVisibleIndexVal = vidx; | 453 if (this.grid) { |
| 390 } | 454 var lastIndex = vidx - vidx % this._itemsPerRow + this._itemsPer
Row - 1; |
| 391 }); | 455 this._lastVisibleIndexVal = lastIndex > this._virtualCount ? thi
s._virtualCount : lastIndex; |
| 456 } else { |
| 457 this._lastVisibleIndexVal = vidx; |
| 458 } |
| 459 } |
| 460 }); |
| 461 } |
| 392 } | 462 } |
| 393 return this._lastVisibleIndexVal; | 463 return this._lastVisibleIndexVal; |
| 394 }, | 464 }, |
| 395 | 465 |
| 396 get _defaultScrollTarget() { | 466 get _defaultScrollTarget() { |
| 397 return this; | 467 return this; |
| 398 }, | 468 }, |
| 469 get _virtualRowCount() { |
| 470 return Math.ceil(this._virtualCount / this._itemsPerRow); |
| 471 }, |
| 472 |
| 473 get _estRowsInView() { |
| 474 return Math.ceil(this._viewportHeight / this._rowHeight); |
| 475 }, |
| 476 |
| 477 get _physicalRows() { |
| 478 return Math.ceil(this._physicalCount / this._itemsPerRow); |
| 479 }, |
| 399 | 480 |
| 400 ready: function() { | 481 ready: function() { |
| 401 this.addEventListener('focus', this._didFocus.bind(this), true); | 482 this.addEventListener('focus', this._didFocus.bind(this), true); |
| 402 }, | 483 }, |
| 403 | 484 |
| 404 attached: function() { | 485 attached: function() { |
| 405 this.updateViewportBoundaries(); | 486 this.updateViewportBoundaries(); |
| 406 this._render(); | 487 this._render(); |
| 407 // `iron-resize` is fired when the list is attached if the event is added | 488 // `iron-resize` is fired when the list is attached if the event is added |
| 408 // before attached causing unnecessary work. | 489 // before attached causing unnecessary work. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 425 /** | 506 /** |
| 426 * Invoke this method if you dynamically update the viewport's | 507 * Invoke this method if you dynamically update the viewport's |
| 427 * size or CSS padding. | 508 * size or CSS padding. |
| 428 * | 509 * |
| 429 * @method updateViewportBoundaries | 510 * @method updateViewportBoundaries |
| 430 */ | 511 */ |
| 431 updateViewportBoundaries: function() { | 512 updateViewportBoundaries: function() { |
| 432 this._scrollerPaddingTop = this.scrollTarget === this ? 0 : | 513 this._scrollerPaddingTop = this.scrollTarget === this ? 0 : |
| 433 parseInt(window.getComputedStyle(this)['padding-top'], 10); | 514 parseInt(window.getComputedStyle(this)['padding-top'], 10); |
| 434 | 515 |
| 435 this._viewportSize = this._scrollTargetHeight; | 516 this._viewportHeight = this._scrollTargetHeight; |
| 517 if (this.grid) { |
| 518 this._updateGridMetrics(); |
| 519 } |
| 436 }, | 520 }, |
| 437 | 521 |
| 438 /** | 522 /** |
| 439 * Update the models, the position of the | 523 * Update the models, the position of the |
| 440 * items in the viewport and recycle tiles as needed. | 524 * items in the viewport and recycle tiles as needed. |
| 441 */ | 525 */ |
| 442 _scrollHandler: function() { | 526 _scrollHandler: function() { |
| 443 // clamp the `scrollTop` value | 527 // clamp the `scrollTop` value |
| 444 var scrollTop = Math.max(0, Math.min(this._maxScrollTop, this._scrollTop))
; | 528 var scrollTop = Math.max(0, Math.min(this._maxScrollTop, this._scrollTop))
; |
| 445 var delta = scrollTop - this._scrollPosition; | 529 var delta = scrollTop - this._scrollPosition; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 | 561 |
| 478 // move tiles from bottom to top | 562 // move tiles from bottom to top |
| 479 while ( | 563 while ( |
| 480 // approximate `currentRatio` to `ratio` | 564 // approximate `currentRatio` to `ratio` |
| 481 currentRatio < ratio && | 565 currentRatio < ratio && |
| 482 // recycle less physical items than the total | 566 // recycle less physical items than the total |
| 483 recycledTiles < this._physicalCount && | 567 recycledTiles < this._physicalCount && |
| 484 // ensure that these recycled tiles are needed | 568 // ensure that these recycled tiles are needed |
| 485 virtualStart - recycledTiles > 0 && | 569 virtualStart - recycledTiles > 0 && |
| 486 // ensure that the tile is not visible | 570 // ensure that the tile is not visible |
| 487 physicalBottom - this._physicalSizes[kth] > scrollBottom | 571 physicalBottom - this._getPhysicalSizeIncrement(kth) > scrollBottom |
| 488 ) { | 572 ) { |
| 489 | 573 |
| 490 tileHeight = this._physicalSizes[kth]; | 574 tileHeight = this._getPhysicalSizeIncrement(kth); |
| 491 currentRatio += tileHeight / hiddenContentSize; | 575 currentRatio += tileHeight / hiddenContentSize; |
| 492 physicalBottom -= tileHeight; | 576 physicalBottom -= tileHeight; |
| 493 recycledTileSet.push(kth); | 577 recycledTileSet.push(kth); |
| 494 recycledTiles++; | 578 recycledTiles++; |
| 495 kth = (kth === 0) ? this._physicalCount - 1 : kth - 1; | 579 kth = (kth === 0) ? this._physicalCount - 1 : kth - 1; |
| 496 } | 580 } |
| 497 | 581 |
| 498 movingUp = recycledTileSet; | 582 movingUp = recycledTileSet; |
| 499 recycledTiles = -recycledTiles; | 583 recycledTiles = -recycledTiles; |
| 500 } | 584 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 511 | 595 |
| 512 // move tiles from top to bottom | 596 // move tiles from top to bottom |
| 513 while ( | 597 while ( |
| 514 // approximate `currentRatio` to `ratio` | 598 // approximate `currentRatio` to `ratio` |
| 515 currentRatio < ratio && | 599 currentRatio < ratio && |
| 516 // recycle less physical items than the total | 600 // recycle less physical items than the total |
| 517 recycledTiles < this._physicalCount && | 601 recycledTiles < this._physicalCount && |
| 518 // ensure that these recycled tiles are needed | 602 // ensure that these recycled tiles are needed |
| 519 virtualEnd + recycledTiles < lastVirtualItemIndex && | 603 virtualEnd + recycledTiles < lastVirtualItemIndex && |
| 520 // ensure that the tile is not visible | 604 // ensure that the tile is not visible |
| 521 this._physicalTop + this._physicalSizes[kth] < scrollTop | 605 this._physicalTop + this._getPhysicalSizeIncrement(kth) < scrollTop |
| 522 ) { | 606 ) { |
| 523 | 607 |
| 524 tileHeight = this._physicalSizes[kth]; | 608 tileHeight = this._getPhysicalSizeIncrement(kth); |
| 525 currentRatio += tileHeight / hiddenContentSize; | 609 currentRatio += tileHeight / hiddenContentSize; |
| 526 | 610 |
| 527 this._physicalTop += tileHeight; | 611 this._physicalTop += tileHeight; |
| 528 recycledTileSet.push(kth); | 612 recycledTileSet.push(kth); |
| 529 recycledTiles++; | 613 recycledTiles++; |
| 530 kth = (kth + 1) % this._physicalCount; | 614 kth = (kth + 1) % this._physicalCount; |
| 531 } | 615 } |
| 532 } | 616 } |
| 533 | 617 |
| 534 if (recycledTiles === 0) { | 618 if (recycledTiles === 0) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 551 _update: function(itemSet, movingUp) { | 635 _update: function(itemSet, movingUp) { |
| 552 // manage focus | 636 // manage focus |
| 553 this._manageFocus(); | 637 this._manageFocus(); |
| 554 // update models | 638 // update models |
| 555 this._assignModels(itemSet); | 639 this._assignModels(itemSet); |
| 556 // measure heights | 640 // measure heights |
| 557 this._updateMetrics(itemSet); | 641 this._updateMetrics(itemSet); |
| 558 // adjust offset after measuring | 642 // adjust offset after measuring |
| 559 if (movingUp) { | 643 if (movingUp) { |
| 560 while (movingUp.length) { | 644 while (movingUp.length) { |
| 561 this._physicalTop -= this._physicalSizes[movingUp.pop()]; | 645 var idx = movingUp.pop(); |
| 646 this._physicalTop -= this._getPhysicalSizeIncrement(idx); |
| 562 } | 647 } |
| 563 } | 648 } |
| 564 // update the position of the items | 649 // update the position of the items |
| 565 this._positionItems(); | 650 this._positionItems(); |
| 566 // set the scroller size | 651 // set the scroller size |
| 567 this._updateScrollerSize(); | 652 this._updateScrollerSize(); |
| 568 // increase the pool of physical items | 653 // increase the pool of physical items |
| 569 this._increasePoolIfNeeded(); | 654 this._increasePoolIfNeeded(); |
| 570 }, | 655 }, |
| 571 | 656 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 586 } | 671 } |
| 587 return physicalItems; | 672 return physicalItems; |
| 588 }, | 673 }, |
| 589 | 674 |
| 590 /** | 675 /** |
| 591 * Increases the pool of physical items only if needed. | 676 * Increases the pool of physical items only if needed. |
| 592 * | 677 * |
| 593 * @return {boolean} True if the pool was increased. | 678 * @return {boolean} True if the pool was increased. |
| 594 */ | 679 */ |
| 595 _increasePoolIfNeeded: function() { | 680 _increasePoolIfNeeded: function() { |
| 596 // Base case 1: the list has no size. | 681 // Base case 1: the list has no height. |
| 597 if (this._viewportSize === 0) { | 682 if (this._viewportHeight === 0) { |
| 598 return false; | 683 return false; |
| 599 } | 684 } |
| 600 // Base case 2: If the physical size is optimal and the list's client heig
ht is full | 685 // Base case 2: If the physical size is optimal and the list's client heig
ht is full |
| 601 // with physical items, don't increase the pool. | 686 // with physical items, don't increase the pool. |
| 602 var isClientHeightFull = this._physicalBottom >= this._scrollBottom && thi
s._physicalTop <= this._scrollPosition; | 687 var isClientHeightFull = this._physicalBottom >= this._scrollBottom && thi
s._physicalTop <= this._scrollPosition; |
| 603 if (this._physicalSize >= this._optPhysicalSize && isClientHeightFull) { | 688 if (this._physicalSize >= this._optPhysicalSize && isClientHeightFull) { |
| 604 return false; | 689 return false; |
| 605 } | 690 } |
| 606 // this value should range between [0 <= `currentPage` <= `_maxPages`] | 691 // this value should range between [0 <= `currentPage` <= `_maxPages`] |
| 607 var currentPage = Math.floor(this._physicalSize / this._viewportSize); | 692 var currentPage = Math.floor(this._physicalSize / this._viewportHeight); |
| 608 | 693 |
| 609 if (currentPage === 0) { | 694 if (currentPage === 0) { |
| 610 // fill the first page | 695 // fill the first page |
| 611 this._debounceTemplate(this._increasePool.bind(this, Math.round(this._ph
ysicalCount * 0.5))); | 696 this._debounceTemplate(this._increasePool.bind(this, Math.round(this._ph
ysicalCount * 0.5))); |
| 612 } else if (this._lastPage !== currentPage && isClientHeightFull) { | 697 } else if (this._lastPage !== currentPage && isClientHeightFull) { |
| 613 // paint the page and defer the next increase | 698 // paint the page and defer the next increase |
| 614 // wait 16ms which is rough enough to get paint cycle. | 699 // wait 16ms which is rough enough to get paint cycle. |
| 615 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', this._increa
sePool.bind(this, 1), 16)); | 700 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', this._increa
sePool.bind(this, this._itemsPerRow), 16)); |
| 616 } else { | 701 } else { |
| 617 // fill the rest of the pages | 702 // fill the rest of the pages |
| 618 this._debounceTemplate(this._increasePool.bind(this, 1)); | 703 this._debounceTemplate(this._increasePool.bind(this, this._itemsPerRow))
; |
| 619 } | 704 } |
| 620 | 705 |
| 621 this._lastPage = currentPage; | 706 this._lastPage = currentPage; |
| 622 | 707 |
| 623 return true; | 708 return true; |
| 624 }, | 709 }, |
| 625 | 710 |
| 626 /** | 711 /** |
| 627 * Increases the pool size. | 712 * Increases the pool size. |
| 628 */ | 713 */ |
| 629 _increasePool: function(missingItems) { | 714 _increasePool: function(missingItems) { |
| 630 var nextPhysicalCount = Math.min( | 715 var nextPhysicalCount = Math.min( |
| 631 this._physicalCount + missingItems, | 716 this._physicalCount + missingItems, |
| 632 this._virtualCount - this._virtualStart, | 717 this._virtualCount - this._virtualStart, |
| 633 MAX_PHYSICAL_COUNT | 718 Math.max(this.maxPhysicalCount, DEFAULT_PHYSICAL_COUNT) |
| 634 ); | 719 ); |
| 635 var prevPhysicalCount = this._physicalCount; | 720 var prevPhysicalCount = this._physicalCount; |
| 636 var delta = nextPhysicalCount - prevPhysicalCount; | 721 var delta = nextPhysicalCount - prevPhysicalCount; |
| 637 | 722 |
| 638 if (delta <= 0) { | 723 if (delta <= 0) { |
| 639 return; | 724 return; |
| 640 } | 725 } |
| 641 | 726 |
| 642 [].push.apply(this._physicalItems, this._createPool(delta)); | 727 [].push.apply(this._physicalItems, this._createPool(delta)); |
| 643 [].push.apply(this._physicalSizes, new Array(delta)); | 728 [].push.apply(this._physicalSizes, new Array(delta)); |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 * | 933 * |
| 849 * @param {!function(number, number)} fn | 934 * @param {!function(number, number)} fn |
| 850 * @param {!Array<number>=} itemSet | 935 * @param {!Array<number>=} itemSet |
| 851 */ | 936 */ |
| 852 _iterateItems: function(fn, itemSet) { | 937 _iterateItems: function(fn, itemSet) { |
| 853 var pidx, vidx, rtn, i; | 938 var pidx, vidx, rtn, i; |
| 854 | 939 |
| 855 if (arguments.length === 2 && itemSet) { | 940 if (arguments.length === 2 && itemSet) { |
| 856 for (i = 0; i < itemSet.length; i++) { | 941 for (i = 0; i < itemSet.length; i++) { |
| 857 pidx = itemSet[i]; | 942 pidx = itemSet[i]; |
| 858 if (pidx >= this._physicalStart) { | 943 vidx = this._computeVidx(pidx); |
| 859 vidx = this._virtualStart + (pidx - this._physicalStart); | |
| 860 } else { | |
| 861 vidx = this._virtualStart + (this._physicalCount - this._physicalSta
rt) + pidx; | |
| 862 } | |
| 863 if ((rtn = fn.call(this, pidx, vidx)) != null) { | 944 if ((rtn = fn.call(this, pidx, vidx)) != null) { |
| 864 return rtn; | 945 return rtn; |
| 865 } | 946 } |
| 866 } | 947 } |
| 867 } else { | 948 } else { |
| 868 pidx = this._physicalStart; | 949 pidx = this._physicalStart; |
| 869 vidx = this._virtualStart; | 950 vidx = this._virtualStart; |
| 870 | 951 |
| 871 for (; pidx < this._physicalCount; pidx++, vidx++) { | 952 for (; pidx < this._physicalCount; pidx++, vidx++) { |
| 872 if ((rtn = fn.call(this, pidx, vidx)) != null) { | 953 if ((rtn = fn.call(this, pidx, vidx)) != null) { |
| 873 return rtn; | 954 return rtn; |
| 874 } | 955 } |
| 875 } | 956 } |
| 876 for (pidx = 0; pidx < this._physicalStart; pidx++, vidx++) { | 957 for (pidx = 0; pidx < this._physicalStart; pidx++, vidx++) { |
| 877 if ((rtn = fn.call(this, pidx, vidx)) != null) { | 958 if ((rtn = fn.call(this, pidx, vidx)) != null) { |
| 878 return rtn; | 959 return rtn; |
| 879 } | 960 } |
| 880 } | 961 } |
| 881 } | 962 } |
| 882 }, | 963 }, |
| 883 | 964 |
| 884 /** | 965 /** |
| 966 * Returns the virtual index for a given physical index |
| 967 * |
| 968 * @param {number} pidx Physical index |
| 969 * @return {number} |
| 970 */ |
| 971 _computeVidx: function(pidx) { |
| 972 if (pidx >= this._physicalStart) { |
| 973 return this._virtualStart + (pidx - this._physicalStart); |
| 974 } |
| 975 return this._virtualStart + (this._physicalCount - this._physicalStart) +
pidx; |
| 976 }, |
| 977 |
| 978 /** |
| 885 * Assigns the data models to a given set of items. | 979 * Assigns the data models to a given set of items. |
| 886 * @param {!Array<number>=} itemSet | 980 * @param {!Array<number>=} itemSet |
| 887 */ | 981 */ |
| 888 _assignModels: function(itemSet) { | 982 _assignModels: function(itemSet) { |
| 889 this._iterateItems(function(pidx, vidx) { | 983 this._iterateItems(function(pidx, vidx) { |
| 890 var el = this._physicalItems[pidx]; | 984 var el = this._physicalItems[pidx]; |
| 891 var inst = el._templateInstance; | 985 var inst = el._templateInstance; |
| 892 var item = this.items && this.items[vidx]; | 986 var item = this.items && this.items[vidx]; |
| 893 | 987 |
| 894 if (item != null) { | 988 if (item != null) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 923 | 1017 |
| 924 this._iterateItems(function(pidx, vidx) { | 1018 this._iterateItems(function(pidx, vidx) { |
| 925 | 1019 |
| 926 oldPhysicalSize += this._physicalSizes[pidx] || 0; | 1020 oldPhysicalSize += this._physicalSizes[pidx] || 0; |
| 927 this._physicalSizes[pidx] = this._physicalItems[pidx].offsetHeight; | 1021 this._physicalSizes[pidx] = this._physicalItems[pidx].offsetHeight; |
| 928 newPhysicalSize += this._physicalSizes[pidx]; | 1022 newPhysicalSize += this._physicalSizes[pidx]; |
| 929 this._physicalAverageCount += this._physicalSizes[pidx] ? 1 : 0; | 1023 this._physicalAverageCount += this._physicalSizes[pidx] ? 1 : 0; |
| 930 | 1024 |
| 931 }, itemSet); | 1025 }, itemSet); |
| 932 | 1026 |
| 933 this._physicalSize = this._physicalSize + newPhysicalSize - oldPhysicalSiz
e; | 1027 this._viewportHeight = this._scrollTargetHeight; |
| 934 this._viewportSize = this._scrollTargetHeight; | 1028 if (this.grid) { |
| 1029 this._updateGridMetrics(); |
| 1030 this._physicalSize = Math.ceil(this._physicalCount / this._itemsPerRow)
* this._rowHeight; |
| 1031 } else { |
| 1032 this._physicalSize = this._physicalSize + newPhysicalSize - oldPhysicalS
ize; |
| 1033 } |
| 935 | 1034 |
| 936 // update the average if we measured something | 1035 // update the average if we measured something |
| 937 if (this._physicalAverageCount !== prevAvgCount) { | 1036 if (this._physicalAverageCount !== prevAvgCount) { |
| 938 this._physicalAverage = Math.round( | 1037 this._physicalAverage = Math.round( |
| 939 ((prevPhysicalAvg * prevAvgCount) + newPhysicalSize) / | 1038 ((prevPhysicalAvg * prevAvgCount) + newPhysicalSize) / |
| 940 this._physicalAverageCount); | 1039 this._physicalAverageCount); |
| 941 } | 1040 } |
| 942 }, | 1041 }, |
| 943 | 1042 |
| 1043 _updateGridMetrics: function() { |
| 1044 this._viewportWidth = this._scrollTargetWidth; |
| 1045 // Set item width to the value of the _physicalItems offsetWidth |
| 1046 this._itemWidth = this._physicalCount > 0 ? this._physicalItems[0].offsetW
idth : DEFAULT_GRID_SIZE; |
| 1047 // Set row height to the value of the _physicalItems offsetHeight |
| 1048 this._rowHeight = this._physicalCount > 0 ? this._physicalItems[0].offsetH
eight : DEFAULT_GRID_SIZE; |
| 1049 // If in grid mode compute how many items with exist in each row |
| 1050 this._itemsPerRow = this._itemWidth ? Math.floor(this._viewportWidth / thi
s._itemWidth) : this._itemsPerRow; |
| 1051 }, |
| 1052 |
| 944 /** | 1053 /** |
| 945 * Updates the position of the physical items. | 1054 * Updates the position of the physical items. |
| 946 */ | 1055 */ |
| 947 _positionItems: function() { | 1056 _positionItems: function() { |
| 948 this._adjustScrollPosition(); | 1057 this._adjustScrollPosition(); |
| 949 | 1058 |
| 950 var y = this._physicalTop; | 1059 var y = this._physicalTop; |
| 951 | 1060 |
| 952 this._iterateItems(function(pidx) { | 1061 if (this.grid) { |
| 953 this.translate3d(0, y + 'px', 0, this._physicalItems[pidx]); | 1062 var totalItemWidth = this._itemsPerRow * this._itemWidth; |
| 954 y += this._physicalSizes[pidx]; | 1063 var rowOffset = (this._viewportWidth - totalItemWidth) / 2; |
| 955 }); | 1064 |
| 1065 this._iterateItems(function(pidx, vidx) { |
| 1066 |
| 1067 var modulus = vidx % this._itemsPerRow; |
| 1068 var x = Math.floor((modulus * this._itemWidth) + rowOffset); |
| 1069 |
| 1070 this.translate3d(x + 'px', y + 'px', 0, this._physicalItems[pidx]); |
| 1071 |
| 1072 if (this._shouldRenderNextRow(vidx)) { |
| 1073 y += this._rowHeight; |
| 1074 } |
| 1075 |
| 1076 }); |
| 1077 } else { |
| 1078 this._iterateItems(function(pidx, vidx) { |
| 1079 |
| 1080 this.translate3d(0, y + 'px', 0, this._physicalItems[pidx]); |
| 1081 y += this._physicalSizes[pidx]; |
| 1082 |
| 1083 }); |
| 1084 } |
| 1085 }, |
| 1086 |
| 1087 _getPhysicalSizeIncrement: function(pidx) { |
| 1088 if (!this.grid) { |
| 1089 return this._physicalSizes[pidx]; |
| 1090 } |
| 1091 if (this._computeVidx(pidx) % this._itemsPerRow !== this._itemsPerRow - 1)
{ |
| 1092 return 0; |
| 1093 } |
| 1094 return this._rowHeight; |
| 956 }, | 1095 }, |
| 957 | 1096 |
| 958 /** | 1097 /** |
| 1098 * Returns, based on the current index, |
| 1099 * whether or not the next index will need |
| 1100 * to be rendered on a new row. |
| 1101 * |
| 1102 * @param {number} vidx Virtual index |
| 1103 * @return {boolean} |
| 1104 */ |
| 1105 _shouldRenderNextRow: function(vidx) { |
| 1106 return vidx % this._itemsPerRow === this._itemsPerRow - 1; |
| 1107 }, |
| 1108 |
| 1109 /** |
| 959 * Adjusts the scroll position when it was overestimated. | 1110 * Adjusts the scroll position when it was overestimated. |
| 960 */ | 1111 */ |
| 961 _adjustScrollPosition: function() { | 1112 _adjustScrollPosition: function() { |
| 962 var deltaHeight = this._virtualStart === 0 ? this._physicalTop : | 1113 var deltaHeight = this._virtualStart === 0 ? this._physicalTop : |
| 963 Math.min(this._scrollPosition + this._physicalTop, 0); | 1114 Math.min(this._scrollPosition + this._physicalTop, 0); |
| 964 | 1115 |
| 965 if (deltaHeight) { | 1116 if (deltaHeight) { |
| 966 this._physicalTop = this._physicalTop - deltaHeight; | 1117 this._physicalTop = this._physicalTop - deltaHeight; |
| 967 // juking scroll position during interial scrolling on iOS is no bueno | 1118 // juking scroll position during interial scrolling on iOS is no bueno |
| 968 if (!IOS_TOUCH_SCROLLING) { | 1119 if (!IOS_TOUCH_SCROLLING) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 980 this._scrollPosition = this._scrollTop; | 1131 this._scrollPosition = this._scrollTop; |
| 981 } | 1132 } |
| 982 }, | 1133 }, |
| 983 | 1134 |
| 984 /** | 1135 /** |
| 985 * Sets the scroll height, that's the height of the content, | 1136 * Sets the scroll height, that's the height of the content, |
| 986 * | 1137 * |
| 987 * @param {boolean=} forceUpdate If true, updates the height no matter what. | 1138 * @param {boolean=} forceUpdate If true, updates the height no matter what. |
| 988 */ | 1139 */ |
| 989 _updateScrollerSize: function(forceUpdate) { | 1140 _updateScrollerSize: function(forceUpdate) { |
| 990 this._estScrollHeight = (this._physicalBottom + | 1141 if (this.grid) { |
| 991 Math.max(this._virtualCount - this._physicalCount - this._virtualStart
, 0) * this._physicalAverage); | 1142 this._estScrollHeight = this._virtualRowCount * this._rowHeight; |
| 1143 } else { |
| 1144 this._estScrollHeight = (this._physicalBottom + |
| 1145 Math.max(this._virtualCount - this._physicalCount - this._virtualSta
rt, 0) * this._physicalAverage); |
| 1146 } |
| 992 | 1147 |
| 993 forceUpdate = forceUpdate || this._scrollHeight === 0; | 1148 forceUpdate = forceUpdate || this._scrollHeight === 0; |
| 994 forceUpdate = forceUpdate || this._scrollPosition >= this._estScrollHeight
- this._physicalSize; | 1149 forceUpdate = forceUpdate || this._scrollPosition >= this._estScrollHeight
- this._physicalSize; |
| 1150 forceUpdate = forceUpdate || this.grid && this.$.items.style.height < this
._estScrollHeight; |
| 995 | 1151 |
| 996 // amortize height adjustment, so it won't trigger repaints very often | 1152 // amortize height adjustment, so it won't trigger repaints very often |
| 997 if (forceUpdate || Math.abs(this._estScrollHeight - this._scrollHeight) >=
this._optPhysicalSize) { | 1153 if (forceUpdate || Math.abs(this._estScrollHeight - this._scrollHeight) >=
this._optPhysicalSize) { |
| 998 this.$.items.style.height = this._estScrollHeight + 'px'; | 1154 this.$.items.style.height = this._estScrollHeight + 'px'; |
| 999 this._scrollHeight = this._estScrollHeight; | 1155 this._scrollHeight = this._estScrollHeight; |
| 1000 } | 1156 } |
| 1001 }, | 1157 }, |
| 1002 /** | 1158 /** |
| 1003 * Scroll to a specific item in the virtual list regardless | 1159 * Scroll to a specific item in the virtual list regardless |
| 1004 * of the physical items in the DOM tree. | 1160 * of the physical items in the DOM tree. |
| 1005 * | 1161 * |
| 1006 * @method scrollToIndex | 1162 * @method scrollToIndex |
| 1007 * @param {number} idx The index of the item | 1163 * @param {number} idx The index of the item |
| 1008 */ | 1164 */ |
| 1009 scrollToIndex: function(idx) { | 1165 scrollToIndex: function(idx) { |
| 1010 if (typeof idx !== 'number') { | 1166 if (typeof idx !== 'number') { |
| 1011 return; | 1167 return; |
| 1012 } | 1168 } |
| 1013 | 1169 |
| 1014 Polymer.dom.flush(); | 1170 Polymer.dom.flush(); |
| 1015 | 1171 |
| 1016 idx = Math.min(Math.max(idx, 0), this._virtualCount-1); | 1172 idx = Math.min(Math.max(idx, 0), this._virtualCount-1); |
| 1017 // update the virtual start only when needed | 1173 // update the virtual start only when needed |
| 1018 if (!this._isIndexRendered(idx) || idx >= this._maxVirtualStart) { | 1174 if (!this._isIndexRendered(idx) || idx >= this._maxVirtualStart) { |
| 1019 this._virtualStart = idx - 1; | 1175 this._virtualStart = this.grid ? (idx - this._itemsPerRow * 2) : (idx -
1); |
| 1020 } | 1176 } |
| 1021 // manage focus | 1177 // manage focus |
| 1022 this._manageFocus(); | 1178 this._manageFocus(); |
| 1023 // assign new models | 1179 // assign new models |
| 1024 this._assignModels(); | 1180 this._assignModels(); |
| 1025 // measure the new sizes | 1181 // measure the new sizes |
| 1026 this._updateMetrics(); | 1182 this._updateMetrics(); |
| 1183 |
| 1027 // estimate new physical offset | 1184 // estimate new physical offset |
| 1028 this._physicalTop = this._virtualStart * this._physicalAverage; | 1185 var estPhysicalTop = Math.floor(this._virtualStart / this._itemsPerRow) *
this._physicalAverage; |
| 1186 this._physicalTop = estPhysicalTop; |
| 1029 | 1187 |
| 1030 var currentTopItem = this._physicalStart; | 1188 var currentTopItem = this._physicalStart; |
| 1031 var currentVirtualItem = this._virtualStart; | 1189 var currentVirtualItem = this._virtualStart; |
| 1032 var targetOffsetTop = 0; | 1190 var targetOffsetTop = 0; |
| 1033 var hiddenContentSize = this._hiddenContentSize; | 1191 var hiddenContentSize = this._hiddenContentSize; |
| 1034 | 1192 |
| 1035 // scroll to the item as much as we can | 1193 // scroll to the item as much as we can |
| 1036 while (currentVirtualItem < idx && targetOffsetTop < hiddenContentSize) { | 1194 while (currentVirtualItem < idx && targetOffsetTop <= hiddenContentSize) { |
| 1037 targetOffsetTop = targetOffsetTop + this._physicalSizes[currentTopItem]; | 1195 targetOffsetTop = targetOffsetTop + this._getPhysicalSizeIncrement(curre
ntTopItem); |
| 1038 currentTopItem = (currentTopItem + 1) % this._physicalCount; | 1196 currentTopItem = (currentTopItem + 1) % this._physicalCount; |
| 1039 currentVirtualItem++; | 1197 currentVirtualItem++; |
| 1040 } | 1198 } |
| 1041 // update the scroller size | 1199 // update the scroller size |
| 1042 this._updateScrollerSize(true); | 1200 this._updateScrollerSize(true); |
| 1043 // update the position of the items | 1201 // update the position of the items |
| 1044 this._positionItems(); | 1202 this._positionItems(); |
| 1045 // set the new scroll position | 1203 // set the new scroll position |
| 1046 this._resetScrollPosition(this._physicalTop + this._scrollerPaddingTop + t
argetOffsetTop); | 1204 this._resetScrollPosition(this._physicalTop + this._scrollerPaddingTop + t
argetOffsetTop); |
| 1047 // increase the pool of physical items if needed | 1205 // increase the pool of physical items if needed |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1058 this._physicalAverage = 0; | 1216 this._physicalAverage = 0; |
| 1059 this._physicalAverageCount = 0; | 1217 this._physicalAverageCount = 0; |
| 1060 }, | 1218 }, |
| 1061 | 1219 |
| 1062 /** | 1220 /** |
| 1063 * A handler for the `iron-resize` event triggered by `IronResizableBehavior
` | 1221 * A handler for the `iron-resize` event triggered by `IronResizableBehavior
` |
| 1064 * when the element is resized. | 1222 * when the element is resized. |
| 1065 */ | 1223 */ |
| 1066 _resizeHandler: function() { | 1224 _resizeHandler: function() { |
| 1067 // iOS fires the resize event when the address bar slides up | 1225 // iOS fires the resize event when the address bar slides up |
| 1068 if (IOS && Math.abs(this._viewportSize - this._scrollTargetHeight) < 100)
{ | 1226 if (IOS && Math.abs(this._viewportHeight - this._scrollTargetHeight) < 100
) { |
| 1069 return; | 1227 return; |
| 1070 } | 1228 } |
| 1071 // In Desktop Safari 9.0.3, if the scroll bars are always shown, | 1229 // In Desktop Safari 9.0.3, if the scroll bars are always shown, |
| 1072 // changing the scroll position from a resize handler would result in | 1230 // changing the scroll position from a resize handler would result in |
| 1073 // the scroll position being reset. Waiting 1ms fixes the issue. | 1231 // the scroll position being reset. Waiting 1ms fixes the issue. |
| 1074 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', | 1232 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', function() { |
| 1075 function() { | 1233 this.updateViewportBoundaries(); |
| 1076 this._render(); | 1234 this._render(); |
| 1077 | 1235 |
| 1078 if (this._itemsRendered && this._physicalItems && this._isVisible) { | 1236 if (this._itemsRendered && this._physicalItems && this._isVisible) { |
| 1079 this._resetAverage(); | 1237 this._resetAverage(); |
| 1080 this.updateViewportBoundaries(); | 1238 this.scrollToIndex(this.firstVisibleIndex); |
| 1081 this.scrollToIndex(this.firstVisibleIndex); | 1239 } |
| 1082 } | 1240 }.bind(this), 1)); |
| 1083 }.bind(this), 1)); | |
| 1084 }, | 1241 }, |
| 1085 | 1242 |
| 1086 _getModelFromItem: function(item) { | 1243 _getModelFromItem: function(item) { |
| 1087 var key = this._collection.getKey(item); | 1244 var key = this._collection.getKey(item); |
| 1088 var pidx = this._physicalIndexForKey[key]; | 1245 var pidx = this._physicalIndexForKey[key]; |
| 1089 | 1246 |
| 1090 if (pidx != null) { | 1247 if (pidx != null) { |
| 1091 return this._physicalItems[pidx]._templateInstance; | 1248 return this._physicalItems[pidx]._templateInstance; |
| 1092 } | 1249 } |
| 1093 return null; | 1250 return null; |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1384 if (hasOffscreenFocusedItem && !this._offscreenFocusedItem) { | 1541 if (hasOffscreenFocusedItem && !this._offscreenFocusedItem) { |
| 1385 this._update(); | 1542 this._update(); |
| 1386 } | 1543 } |
| 1387 } | 1544 } |
| 1388 }, | 1545 }, |
| 1389 | 1546 |
| 1390 _didMoveUp: function() { | 1547 _didMoveUp: function() { |
| 1391 this._focusPhysicalItem(this._focusedIndex - 1); | 1548 this._focusPhysicalItem(this._focusedIndex - 1); |
| 1392 }, | 1549 }, |
| 1393 | 1550 |
| 1394 _didMoveDown: function() { | 1551 _didMoveDown: function(e) { |
| 1552 // disable scroll when pressing the down key |
| 1553 e.detail.keyboardEvent.preventDefault(); |
| 1395 this._focusPhysicalItem(this._focusedIndex + 1); | 1554 this._focusPhysicalItem(this._focusedIndex + 1); |
| 1396 }, | 1555 }, |
| 1397 | 1556 |
| 1398 _didEnter: function(e) { | 1557 _didEnter: function(e) { |
| 1399 this._focusPhysicalItem(this._focusedIndex); | 1558 this._focusPhysicalItem(this._focusedIndex); |
| 1400 this._selectionHandler(e.detail.keyboardEvent); | 1559 this._selectionHandler(e.detail.keyboardEvent); |
| 1401 } | 1560 } |
| 1402 }); | 1561 }); |
| 1403 | 1562 |
| 1404 })(); | 1563 })(); |
| OLD | NEW |