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

Side by Side Diff: chrome/browser/resources/md_downloads/crisper.js

Issue 1901343004: [Polymer] update third_party polymer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview Assertion support. 6 * @fileoverview Assertion support.
7 */ 7 */
8 8
9 /** 9 /**
10 * Verify |condition| is truthy and return |condition| if so. 10 * Verify |condition| is truthy and return |condition| if so.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 * ... 86 * ...
87 * ... 87 * ...
88 * resolver.resolve({hello: 'world'}); 88 * resolver.resolve({hello: 'world'});
89 */ 89 */
90 90
91 /** 91 /**
92 * @constructor @struct 92 * @constructor @struct
93 * @template T 93 * @template T
94 */ 94 */
95 function PromiseResolver() { 95 function PromiseResolver() {
96 /** @private {function(T): void} */ 96 /** @private {function(T=): void} */
97 this.resolve_; 97 this.resolve_;
98 98
99 /** @private {function(*=): void} */ 99 /** @private {function(*=): void} */
100 this.reject_; 100 this.reject_;
101 101
102 /** @private {!Promise<T>} */ 102 /** @private {!Promise<T>} */
103 this.promise_ = new Promise(function(resolve, reject) { 103 this.promise_ = new Promise(function(resolve, reject) {
104 this.resolve_ = resolve; 104 this.resolve_ = resolve;
105 this.reject_ = reject; 105 this.reject_ = reject;
106 }.bind(this)); 106 }.bind(this));
107 } 107 }
108 108
109 PromiseResolver.prototype = { 109 PromiseResolver.prototype = {
110 /** @return {!Promise<T>} */ 110 /** @return {!Promise<T>} */
111 get promise() { return this.promise_; }, 111 get promise() { return this.promise_; },
112 set promise(p) { assertNotReached(); }, 112 set promise(p) { assertNotReached(); },
113 113
114 /** @return {function(T): void} */ 114 /** @return {function(T=): void} */
115 get resolve() { return this.resolve_; }, 115 get resolve() { return this.resolve_; },
116 set resolve(r) { assertNotReached(); }, 116 set resolve(r) { assertNotReached(); },
117 117
118 /** @return {function(*=): void} */ 118 /** @return {function(*=): void} */
119 get reject() { return this.reject_; }, 119 get reject() { return this.reject_; },
120 set reject(s) { assertNotReached(); }, 120 set reject(s) { assertNotReached(); },
121 }; 121 };
122 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 122 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
123 // Use of this source code is governed by a BSD-style license that can be 123 // Use of this source code is governed by a BSD-style license that can be
124 // found in the LICENSE file. 124 // found in the LICENSE file.
(...skipping 2336 matching lines...) Expand 10 before | Expand all | Expand 10 after
2461 */ 2461 */
2462 _isValidScrollTarget: function() { 2462 _isValidScrollTarget: function() {
2463 return this.scrollTarget instanceof HTMLElement; 2463 return this.scrollTarget instanceof HTMLElement;
2464 } 2464 }
2465 }; 2465 };
2466 (function() { 2466 (function() {
2467 2467
2468 var IOS = navigator.userAgent.match(/iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/); 2468 var IOS = navigator.userAgent.match(/iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/);
2469 var IOS_TOUCH_SCROLLING = IOS && IOS[1] >= 8; 2469 var IOS_TOUCH_SCROLLING = IOS && IOS[1] >= 8;
2470 var DEFAULT_PHYSICAL_COUNT = 3; 2470 var DEFAULT_PHYSICAL_COUNT = 3;
2471 var MAX_PHYSICAL_COUNT = 500;
2472 var HIDDEN_Y = '-10000px'; 2471 var HIDDEN_Y = '-10000px';
2472 var DEFAULT_GRID_SIZE = 200;
2473 2473
2474 Polymer({ 2474 Polymer({
2475 2475
2476 is: 'iron-list', 2476 is: 'iron-list',
2477 2477
2478 properties: { 2478 properties: {
2479 2479
2480 /** 2480 /**
2481 * An array containing items determining how many instances of the templat e 2481 * An array containing items determining how many instances of the templat e
2482 * to stamp and that that each template instance should bind to. 2482 * to stamp and that that each template instance should bind to.
2483 */ 2483 */
2484 items: { 2484 items: {
2485 type: Array 2485 type: Array
2486 }, 2486 },
2487 2487
2488 /** 2488 /**
2489 * The max count of physical items the pool can extend to.
2490 */
2491 maxPhysicalCount: {
2492 type: Number,
2493 value: 500
2494 },
2495
2496 /**
2489 * The name of the variable to add to the binding scope for the array 2497 * The name of the variable to add to the binding scope for the array
2490 * element associated with a given template instance. 2498 * element associated with a given template instance.
2491 */ 2499 */
2492 as: { 2500 as: {
2493 type: String, 2501 type: String,
2494 value: 'item' 2502 value: 'item'
2495 }, 2503 },
2496 2504
2497 /** 2505 /**
2498 * The name of the variable to add to the binding scope with the index 2506 * The name of the variable to add to the binding scope with the index
2499 * for the row. 2507 * for the row.
2500 */ 2508 */
2501 indexAs: { 2509 indexAs: {
2502 type: String, 2510 type: String,
2503 value: 'index' 2511 value: 'index'
2504 }, 2512 },
2505 2513
2506 /** 2514 /**
2507 * The name of the variable to add to the binding scope to indicate 2515 * The name of the variable to add to the binding scope to indicate
2508 * if the row is selected. 2516 * if the row is selected.
2509 */ 2517 */
2510 selectedAs: { 2518 selectedAs: {
2511 type: String, 2519 type: String,
2512 value: 'selected' 2520 value: 'selected'
2513 }, 2521 },
2514 2522
2515 /** 2523 /**
2524 * When true, the list is rendered as a grid. Grid items must have
2525 * fixed width and height set via CSS. e.g.
2526 *
2527 * ```html
2528 * <iron-list grid>
2529 * <template>
2530 * <div style="width: 100px; height: 100px;"> 100x100 </div>
2531 * </template>
2532 * </iron-list>
2533 * ```
2534 */
2535 grid: {
2536 type: Boolean,
2537 value: false,
2538 reflectToAttribute: true
2539 },
2540
2541 /**
2516 * When true, tapping a row will select the item, placing its data model 2542 * When true, tapping a row will select the item, placing its data model
2517 * in the set of selected items retrievable via the selection property. 2543 * in the set of selected items retrievable via the selection property.
2518 * 2544 *
2519 * Note that tapping focusable elements within the list item will not 2545 * Note that tapping focusable elements within the list item will not
2520 * result in selection, since they are presumed to have their * own action . 2546 * result in selection, since they are presumed to have their * own action .
2521 */ 2547 */
2522 selectionEnabled: { 2548 selectionEnabled: {
2523 type: Boolean, 2549 type: Boolean,
2524 value: false 2550 value: false
2525 }, 2551 },
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
2625 _estScrollHeight: 0, 2651 _estScrollHeight: 0,
2626 2652
2627 /** 2653 /**
2628 * The scroll height of the dom node 2654 * The scroll height of the dom node
2629 */ 2655 */
2630 _scrollHeight: 0, 2656 _scrollHeight: 0,
2631 2657
2632 /** 2658 /**
2633 * The height of the list. This is referred as the viewport in the context o f list. 2659 * The height of the list. This is referred as the viewport in the context o f list.
2634 */ 2660 */
2635 _viewportSize: 0, 2661 _viewportHeight: 0,
2662
2663 /**
2664 * The width of the list. This is referred as the viewport in the context of list.
2665 */
2666 _viewportWidth: 0,
2636 2667
2637 /** 2668 /**
2638 * An array of DOM nodes that are currently in the tree 2669 * An array of DOM nodes that are currently in the tree
2639 * @type {?Array<!TemplatizerNode>} 2670 * @type {?Array<!TemplatizerNode>}
2640 */ 2671 */
2641 _physicalItems: null, 2672 _physicalItems: null,
2642 2673
2643 /** 2674 /**
2644 * An array of heights for each item in `_physicalItems` 2675 * An array of heights for each item in `_physicalItems`
2645 * @type {?Array<number>} 2676 * @type {?Array<number>}
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2698 */ 2729 */
2699 _offscreenFocusedItem: null, 2730 _offscreenFocusedItem: null,
2700 2731
2701 /** 2732 /**
2702 * The item that backfills the `_offscreenFocusedItem` in the physical items 2733 * The item that backfills the `_offscreenFocusedItem` in the physical items
2703 * list when that item is moved offscreen. 2734 * list when that item is moved offscreen.
2704 */ 2735 */
2705 _focusBackfillItem: null, 2736 _focusBackfillItem: null,
2706 2737
2707 /** 2738 /**
2739 * The maximum items per row
2740 */
2741 _itemsPerRow: 1,
2742
2743 /**
2744 * The width of each grid item
2745 */
2746 _itemWidth: 0,
2747
2748 /**
2749 * The height of the row in grid layout.
2750 */
2751 _rowHeight: 0,
2752
2753 /**
2708 * The bottom of the physical content. 2754 * The bottom of the physical content.
2709 */ 2755 */
2710 get _physicalBottom() { 2756 get _physicalBottom() {
2711 return this._physicalTop + this._physicalSize; 2757 return this._physicalTop + this._physicalSize;
2712 }, 2758 },
2713 2759
2714 /** 2760 /**
2715 * The bottom of the scroll. 2761 * The bottom of the scroll.
2716 */ 2762 */
2717 get _scrollBottom() { 2763 get _scrollBottom() {
2718 return this._scrollPosition + this._viewportSize; 2764 return this._scrollPosition + this._viewportHeight;
2719 }, 2765 },
2720 2766
2721 /** 2767 /**
2722 * The n-th item rendered in the last physical item. 2768 * The n-th item rendered in the last physical item.
2723 */ 2769 */
2724 get _virtualEnd() { 2770 get _virtualEnd() {
2725 return this._virtualStart + this._physicalCount - 1; 2771 return this._virtualStart + this._physicalCount - 1;
2726 }, 2772 },
2727 2773
2728 /** 2774 /**
2729 * The height of the physical content that isn't on the screen. 2775 * The height of the physical content that isn't on the screen.
2730 */ 2776 */
2731 get _hiddenContentSize() { 2777 get _hiddenContentSize() {
2732 return this._physicalSize - this._viewportSize; 2778 var size = this.grid ? this._physicalRows * this._rowHeight : this._physic alSize;
2779 return size - this._viewportHeight;
2733 }, 2780 },
2734 2781
2735 /** 2782 /**
2736 * The maximum scroll top value. 2783 * The maximum scroll top value.
2737 */ 2784 */
2738 get _maxScrollTop() { 2785 get _maxScrollTop() {
2739 return this._estScrollHeight - this._viewportSize + this._scrollerPaddingT op; 2786 return this._estScrollHeight - this._viewportHeight + this._scrollerPaddin gTop;
2740 }, 2787 },
2741 2788
2742 /** 2789 /**
2743 * The lowest n-th value for an item such that it can be rendered in `_physi calStart`. 2790 * The lowest n-th value for an item such that it can be rendered in `_physi calStart`.
2744 */ 2791 */
2745 _minVirtualStart: 0, 2792 _minVirtualStart: 0,
2746 2793
2747 /** 2794 /**
2748 * The largest n-th value for an item such that it can be rendered in `_phys icalStart`. 2795 * The largest n-th value for an item such that it can be rendered in `_phys icalStart`.
2749 */ 2796 */
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2801 _physicalEnd: 0, 2848 _physicalEnd: 0,
2802 2849
2803 /** 2850 /**
2804 * An optimal physical size such that we will have enough physical items 2851 * An optimal physical size such that we will have enough physical items
2805 * to fill up the viewport and recycle when the user scrolls. 2852 * to fill up the viewport and recycle when the user scrolls.
2806 * 2853 *
2807 * This default value assumes that we will at least have the equivalent 2854 * This default value assumes that we will at least have the equivalent
2808 * to a viewport of physical items above and below the user's viewport. 2855 * to a viewport of physical items above and below the user's viewport.
2809 */ 2856 */
2810 get _optPhysicalSize() { 2857 get _optPhysicalSize() {
2811 return this._viewportSize * this._maxPages; 2858 if (this.grid) {
2859 return this._estRowsInView * this._rowHeight * this._maxPages;
2860 }
2861 return this._viewportHeight * this._maxPages;
2862 },
2863
2864 get _optPhysicalCount() {
2865 return this._estRowsInView * this._itemsPerRow * this._maxPages;
2812 }, 2866 },
2813 2867
2814 /** 2868 /**
2815 * True if the current list is visible. 2869 * True if the current list is visible.
2816 */ 2870 */
2817 get _isVisible() { 2871 get _isVisible() {
2818 return this.scrollTarget && Boolean(this.scrollTarget.offsetWidth || this. scrollTarget.offsetHeight); 2872 return this.scrollTarget && Boolean(this.scrollTarget.offsetWidth || this. scrollTarget.offsetHeight);
2819 }, 2873 },
2820 2874
2821 /** 2875 /**
2822 * Gets the index of the first visible item in the viewport. 2876 * Gets the index of the first visible item in the viewport.
2823 * 2877 *
2824 * @type {number} 2878 * @type {number}
2825 */ 2879 */
2826 get firstVisibleIndex() { 2880 get firstVisibleIndex() {
2827 if (this._firstVisibleIndexVal === null) { 2881 if (this._firstVisibleIndexVal === null) {
2828 var physicalOffset = this._physicalTop + this._scrollerPaddingTop; 2882 var physicalOffset = Math.floor(this._physicalTop + this._scrollerPaddin gTop);
2829 2883
2830 this._firstVisibleIndexVal = this._iterateItems( 2884 this._firstVisibleIndexVal = this._iterateItems(
2831 function(pidx, vidx) { 2885 function(pidx, vidx) {
2832 physicalOffset += this._physicalSizes[pidx]; 2886 physicalOffset += this._getPhysicalSizeIncrement(pidx);
2887
2833 if (physicalOffset > this._scrollPosition) { 2888 if (physicalOffset > this._scrollPosition) {
2834 return vidx; 2889 return this.grid ? vidx - (vidx % this._itemsPerRow) : vidx;
2890 }
2891
2892 // Handle a partially rendered final row in grid mode
2893 if (this.grid && this._virtualCount - 1 === vidx) {
2894 return vidx - (vidx % this._itemsPerRow);
2835 } 2895 }
2836 }) || 0; 2896 }) || 0;
2837 } 2897 }
2838 return this._firstVisibleIndexVal; 2898 return this._firstVisibleIndexVal;
2839 }, 2899 },
2840 2900
2841 /** 2901 /**
2842 * Gets the index of the last visible item in the viewport. 2902 * Gets the index of the last visible item in the viewport.
2843 * 2903 *
2844 * @type {number} 2904 * @type {number}
2845 */ 2905 */
2846 get lastVisibleIndex() { 2906 get lastVisibleIndex() {
2847 if (this._lastVisibleIndexVal === null) { 2907 if (this._lastVisibleIndexVal === null) {
2848 var physicalOffset = this._physicalTop; 2908 if (this.grid) {
2909 var lastIndex = this.firstVisibleIndex + this._estRowsInView * this._i temsPerRow - 1;
2910 this._lastVisibleIndexVal = lastIndex > this._virtualCount ? this._vir tualCount : lastIndex;
2911 } else {
2912 var physicalOffset = this._physicalTop;
2849 2913
2850 this._iterateItems(function(pidx, vidx) { 2914 this._iterateItems(function(pidx, vidx) {
2851 physicalOffset += this._physicalSizes[pidx]; 2915 physicalOffset += this._getPhysicalSizeIncrement(pidx);
2852 2916
2853 if (physicalOffset <= this._scrollBottom) { 2917 if(physicalOffset <= this._scrollBottom) {
2854 this._lastVisibleIndexVal = vidx; 2918 if (this.grid) {
2855 } 2919 var lastIndex = vidx - vidx % this._itemsPerRow + this._itemsPer Row - 1;
2856 }); 2920 this._lastVisibleIndexVal = lastIndex > this._virtualCount ? thi s._virtualCount : lastIndex;
2921 } else {
2922 this._lastVisibleIndexVal = vidx;
2923 }
2924 }
2925 });
2926 }
2857 } 2927 }
2858 return this._lastVisibleIndexVal; 2928 return this._lastVisibleIndexVal;
2859 }, 2929 },
2860 2930
2861 get _defaultScrollTarget() { 2931 get _defaultScrollTarget() {
2862 return this; 2932 return this;
2863 }, 2933 },
2934 get _virtualRowCount() {
2935 return Math.ceil(this._virtualCount / this._itemsPerRow);
2936 },
2937
2938 get _estRowsInView() {
2939 return Math.ceil(this._viewportHeight / this._rowHeight);
2940 },
2941
2942 get _physicalRows() {
2943 return Math.ceil(this._physicalCount / this._itemsPerRow);
2944 },
2864 2945
2865 ready: function() { 2946 ready: function() {
2866 this.addEventListener('focus', this._didFocus.bind(this), true); 2947 this.addEventListener('focus', this._didFocus.bind(this), true);
2867 }, 2948 },
2868 2949
2869 attached: function() { 2950 attached: function() {
2870 this.updateViewportBoundaries(); 2951 this.updateViewportBoundaries();
2871 this._render(); 2952 this._render();
2872 // `iron-resize` is fired when the list is attached if the event is added 2953 // `iron-resize` is fired when the list is attached if the event is added
2873 // before attached causing unnecessary work. 2954 // before attached causing unnecessary work.
(...skipping 16 matching lines...) Expand all
2890 /** 2971 /**
2891 * Invoke this method if you dynamically update the viewport's 2972 * Invoke this method if you dynamically update the viewport's
2892 * size or CSS padding. 2973 * size or CSS padding.
2893 * 2974 *
2894 * @method updateViewportBoundaries 2975 * @method updateViewportBoundaries
2895 */ 2976 */
2896 updateViewportBoundaries: function() { 2977 updateViewportBoundaries: function() {
2897 this._scrollerPaddingTop = this.scrollTarget === this ? 0 : 2978 this._scrollerPaddingTop = this.scrollTarget === this ? 0 :
2898 parseInt(window.getComputedStyle(this)['padding-top'], 10); 2979 parseInt(window.getComputedStyle(this)['padding-top'], 10);
2899 2980
2900 this._viewportSize = this._scrollTargetHeight; 2981 this._viewportHeight = this._scrollTargetHeight;
2982 if (this.grid) {
2983 this._updateGridMetrics();
2984 }
2901 }, 2985 },
2902 2986
2903 /** 2987 /**
2904 * Update the models, the position of the 2988 * Update the models, the position of the
2905 * items in the viewport and recycle tiles as needed. 2989 * items in the viewport and recycle tiles as needed.
2906 */ 2990 */
2907 _scrollHandler: function() { 2991 _scrollHandler: function() {
2908 // clamp the `scrollTop` value 2992 // clamp the `scrollTop` value
2909 var scrollTop = Math.max(0, Math.min(this._maxScrollTop, this._scrollTop)) ; 2993 var scrollTop = Math.max(0, Math.min(this._maxScrollTop, this._scrollTop)) ;
2910 var delta = scrollTop - this._scrollPosition; 2994 var delta = scrollTop - this._scrollPosition;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2942 3026
2943 // move tiles from bottom to top 3027 // move tiles from bottom to top
2944 while ( 3028 while (
2945 // approximate `currentRatio` to `ratio` 3029 // approximate `currentRatio` to `ratio`
2946 currentRatio < ratio && 3030 currentRatio < ratio &&
2947 // recycle less physical items than the total 3031 // recycle less physical items than the total
2948 recycledTiles < this._physicalCount && 3032 recycledTiles < this._physicalCount &&
2949 // ensure that these recycled tiles are needed 3033 // ensure that these recycled tiles are needed
2950 virtualStart - recycledTiles > 0 && 3034 virtualStart - recycledTiles > 0 &&
2951 // ensure that the tile is not visible 3035 // ensure that the tile is not visible
2952 physicalBottom - this._physicalSizes[kth] > scrollBottom 3036 physicalBottom - this._getPhysicalSizeIncrement(kth) > scrollBottom
2953 ) { 3037 ) {
2954 3038
2955 tileHeight = this._physicalSizes[kth]; 3039 tileHeight = this._getPhysicalSizeIncrement(kth);
2956 currentRatio += tileHeight / hiddenContentSize; 3040 currentRatio += tileHeight / hiddenContentSize;
2957 physicalBottom -= tileHeight; 3041 physicalBottom -= tileHeight;
2958 recycledTileSet.push(kth); 3042 recycledTileSet.push(kth);
2959 recycledTiles++; 3043 recycledTiles++;
2960 kth = (kth === 0) ? this._physicalCount - 1 : kth - 1; 3044 kth = (kth === 0) ? this._physicalCount - 1 : kth - 1;
2961 } 3045 }
2962 3046
2963 movingUp = recycledTileSet; 3047 movingUp = recycledTileSet;
2964 recycledTiles = -recycledTiles; 3048 recycledTiles = -recycledTiles;
2965 } 3049 }
(...skipping 10 matching lines...) Expand all
2976 3060
2977 // move tiles from top to bottom 3061 // move tiles from top to bottom
2978 while ( 3062 while (
2979 // approximate `currentRatio` to `ratio` 3063 // approximate `currentRatio` to `ratio`
2980 currentRatio < ratio && 3064 currentRatio < ratio &&
2981 // recycle less physical items than the total 3065 // recycle less physical items than the total
2982 recycledTiles < this._physicalCount && 3066 recycledTiles < this._physicalCount &&
2983 // ensure that these recycled tiles are needed 3067 // ensure that these recycled tiles are needed
2984 virtualEnd + recycledTiles < lastVirtualItemIndex && 3068 virtualEnd + recycledTiles < lastVirtualItemIndex &&
2985 // ensure that the tile is not visible 3069 // ensure that the tile is not visible
2986 this._physicalTop + this._physicalSizes[kth] < scrollTop 3070 this._physicalTop + this._getPhysicalSizeIncrement(kth) < scrollTop
2987 ) { 3071 ) {
2988 3072
2989 tileHeight = this._physicalSizes[kth]; 3073 tileHeight = this._getPhysicalSizeIncrement(kth);
2990 currentRatio += tileHeight / hiddenContentSize; 3074 currentRatio += tileHeight / hiddenContentSize;
2991 3075
2992 this._physicalTop += tileHeight; 3076 this._physicalTop += tileHeight;
2993 recycledTileSet.push(kth); 3077 recycledTileSet.push(kth);
2994 recycledTiles++; 3078 recycledTiles++;
2995 kth = (kth + 1) % this._physicalCount; 3079 kth = (kth + 1) % this._physicalCount;
2996 } 3080 }
2997 } 3081 }
2998 3082
2999 if (recycledTiles === 0) { 3083 if (recycledTiles === 0) {
(...skipping 16 matching lines...) Expand all
3016 _update: function(itemSet, movingUp) { 3100 _update: function(itemSet, movingUp) {
3017 // manage focus 3101 // manage focus
3018 this._manageFocus(); 3102 this._manageFocus();
3019 // update models 3103 // update models
3020 this._assignModels(itemSet); 3104 this._assignModels(itemSet);
3021 // measure heights 3105 // measure heights
3022 this._updateMetrics(itemSet); 3106 this._updateMetrics(itemSet);
3023 // adjust offset after measuring 3107 // adjust offset after measuring
3024 if (movingUp) { 3108 if (movingUp) {
3025 while (movingUp.length) { 3109 while (movingUp.length) {
3026 this._physicalTop -= this._physicalSizes[movingUp.pop()]; 3110 var idx = movingUp.pop();
3111 this._physicalTop -= this._getPhysicalSizeIncrement(idx);
3027 } 3112 }
3028 } 3113 }
3029 // update the position of the items 3114 // update the position of the items
3030 this._positionItems(); 3115 this._positionItems();
3031 // set the scroller size 3116 // set the scroller size
3032 this._updateScrollerSize(); 3117 this._updateScrollerSize();
3033 // increase the pool of physical items 3118 // increase the pool of physical items
3034 this._increasePoolIfNeeded(); 3119 this._increasePoolIfNeeded();
3035 }, 3120 },
3036 3121
(...skipping 14 matching lines...) Expand all
3051 } 3136 }
3052 return physicalItems; 3137 return physicalItems;
3053 }, 3138 },
3054 3139
3055 /** 3140 /**
3056 * Increases the pool of physical items only if needed. 3141 * Increases the pool of physical items only if needed.
3057 * 3142 *
3058 * @return {boolean} True if the pool was increased. 3143 * @return {boolean} True if the pool was increased.
3059 */ 3144 */
3060 _increasePoolIfNeeded: function() { 3145 _increasePoolIfNeeded: function() {
3061 // Base case 1: the list has no size. 3146 // Base case 1: the list has no height.
3062 if (this._viewportSize === 0) { 3147 if (this._viewportHeight === 0) {
3063 return false; 3148 return false;
3064 } 3149 }
3065 // Base case 2: If the physical size is optimal and the list's client heig ht is full 3150 // Base case 2: If the physical size is optimal and the list's client heig ht is full
3066 // with physical items, don't increase the pool. 3151 // with physical items, don't increase the pool.
3067 var isClientHeightFull = this._physicalBottom >= this._scrollBottom && thi s._physicalTop <= this._scrollPosition; 3152 var isClientHeightFull = this._physicalBottom >= this._scrollBottom && thi s._physicalTop <= this._scrollPosition;
3068 if (this._physicalSize >= this._optPhysicalSize && isClientHeightFull) { 3153 if (this._physicalSize >= this._optPhysicalSize && isClientHeightFull) {
3069 return false; 3154 return false;
3070 } 3155 }
3071 // this value should range between [0 <= `currentPage` <= `_maxPages`] 3156 // this value should range between [0 <= `currentPage` <= `_maxPages`]
3072 var currentPage = Math.floor(this._physicalSize / this._viewportSize); 3157 var currentPage = Math.floor(this._physicalSize / this._viewportHeight);
3073 3158
3074 if (currentPage === 0) { 3159 if (currentPage === 0) {
3075 // fill the first page 3160 // fill the first page
3076 this._debounceTemplate(this._increasePool.bind(this, Math.round(this._ph ysicalCount * 0.5))); 3161 this._debounceTemplate(this._increasePool.bind(this, Math.round(this._ph ysicalCount * 0.5)));
3077 } else if (this._lastPage !== currentPage && isClientHeightFull) { 3162 } else if (this._lastPage !== currentPage && isClientHeightFull) {
3078 // paint the page and defer the next increase 3163 // paint the page and defer the next increase
3079 // wait 16ms which is rough enough to get paint cycle. 3164 // wait 16ms which is rough enough to get paint cycle.
3080 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', this._increa sePool.bind(this, 1), 16)); 3165 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', this._increa sePool.bind(this, this._itemsPerRow), 16));
3081 } else { 3166 } else {
3082 // fill the rest of the pages 3167 // fill the rest of the pages
3083 this._debounceTemplate(this._increasePool.bind(this, 1)); 3168 this._debounceTemplate(this._increasePool.bind(this, this._itemsPerRow)) ;
3084 } 3169 }
3085 3170
3086 this._lastPage = currentPage; 3171 this._lastPage = currentPage;
3087 3172
3088 return true; 3173 return true;
3089 }, 3174 },
3090 3175
3091 /** 3176 /**
3092 * Increases the pool size. 3177 * Increases the pool size.
3093 */ 3178 */
3094 _increasePool: function(missingItems) { 3179 _increasePool: function(missingItems) {
3095 var nextPhysicalCount = Math.min( 3180 var nextPhysicalCount = Math.min(
3096 this._physicalCount + missingItems, 3181 this._physicalCount + missingItems,
3097 this._virtualCount - this._virtualStart, 3182 this._virtualCount - this._virtualStart,
3098 MAX_PHYSICAL_COUNT 3183 Math.max(this.maxPhysicalCount, DEFAULT_PHYSICAL_COUNT)
3099 ); 3184 );
3100 var prevPhysicalCount = this._physicalCount; 3185 var prevPhysicalCount = this._physicalCount;
3101 var delta = nextPhysicalCount - prevPhysicalCount; 3186 var delta = nextPhysicalCount - prevPhysicalCount;
3102 3187
3103 if (delta <= 0) { 3188 if (delta <= 0) {
3104 return; 3189 return;
3105 } 3190 }
3106 3191
3107 [].push.apply(this._physicalItems, this._createPool(delta)); 3192 [].push.apply(this._physicalItems, this._createPool(delta));
3108 [].push.apply(this._physicalSizes, new Array(delta)); 3193 [].push.apply(this._physicalSizes, new Array(delta));
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
3313 * 3398 *
3314 * @param {!function(number, number)} fn 3399 * @param {!function(number, number)} fn
3315 * @param {!Array<number>=} itemSet 3400 * @param {!Array<number>=} itemSet
3316 */ 3401 */
3317 _iterateItems: function(fn, itemSet) { 3402 _iterateItems: function(fn, itemSet) {
3318 var pidx, vidx, rtn, i; 3403 var pidx, vidx, rtn, i;
3319 3404
3320 if (arguments.length === 2 && itemSet) { 3405 if (arguments.length === 2 && itemSet) {
3321 for (i = 0; i < itemSet.length; i++) { 3406 for (i = 0; i < itemSet.length; i++) {
3322 pidx = itemSet[i]; 3407 pidx = itemSet[i];
3323 if (pidx >= this._physicalStart) { 3408 vidx = this._computeVidx(pidx);
3324 vidx = this._virtualStart + (pidx - this._physicalStart);
3325 } else {
3326 vidx = this._virtualStart + (this._physicalCount - this._physicalSta rt) + pidx;
3327 }
3328 if ((rtn = fn.call(this, pidx, vidx)) != null) { 3409 if ((rtn = fn.call(this, pidx, vidx)) != null) {
3329 return rtn; 3410 return rtn;
3330 } 3411 }
3331 } 3412 }
3332 } else { 3413 } else {
3333 pidx = this._physicalStart; 3414 pidx = this._physicalStart;
3334 vidx = this._virtualStart; 3415 vidx = this._virtualStart;
3335 3416
3336 for (; pidx < this._physicalCount; pidx++, vidx++) { 3417 for (; pidx < this._physicalCount; pidx++, vidx++) {
3337 if ((rtn = fn.call(this, pidx, vidx)) != null) { 3418 if ((rtn = fn.call(this, pidx, vidx)) != null) {
3338 return rtn; 3419 return rtn;
3339 } 3420 }
3340 } 3421 }
3341 for (pidx = 0; pidx < this._physicalStart; pidx++, vidx++) { 3422 for (pidx = 0; pidx < this._physicalStart; pidx++, vidx++) {
3342 if ((rtn = fn.call(this, pidx, vidx)) != null) { 3423 if ((rtn = fn.call(this, pidx, vidx)) != null) {
3343 return rtn; 3424 return rtn;
3344 } 3425 }
3345 } 3426 }
3346 } 3427 }
3347 }, 3428 },
3348 3429
3349 /** 3430 /**
3431 * Returns the virtual index for a given physical index
3432 *
3433 * @param {number} pidx Physical index
3434 * @return {number}
3435 */
3436 _computeVidx: function(pidx) {
3437 if (pidx >= this._physicalStart) {
3438 return this._virtualStart + (pidx - this._physicalStart);
3439 }
3440 return this._virtualStart + (this._physicalCount - this._physicalStart) + pidx;
3441 },
3442
3443 /**
3350 * Assigns the data models to a given set of items. 3444 * Assigns the data models to a given set of items.
3351 * @param {!Array<number>=} itemSet 3445 * @param {!Array<number>=} itemSet
3352 */ 3446 */
3353 _assignModels: function(itemSet) { 3447 _assignModels: function(itemSet) {
3354 this._iterateItems(function(pidx, vidx) { 3448 this._iterateItems(function(pidx, vidx) {
3355 var el = this._physicalItems[pidx]; 3449 var el = this._physicalItems[pidx];
3356 var inst = el._templateInstance; 3450 var inst = el._templateInstance;
3357 var item = this.items && this.items[vidx]; 3451 var item = this.items && this.items[vidx];
3358 3452
3359 if (item != null) { 3453 if (item != null) {
(...skipping 28 matching lines...) Expand all
3388 3482
3389 this._iterateItems(function(pidx, vidx) { 3483 this._iterateItems(function(pidx, vidx) {
3390 3484
3391 oldPhysicalSize += this._physicalSizes[pidx] || 0; 3485 oldPhysicalSize += this._physicalSizes[pidx] || 0;
3392 this._physicalSizes[pidx] = this._physicalItems[pidx].offsetHeight; 3486 this._physicalSizes[pidx] = this._physicalItems[pidx].offsetHeight;
3393 newPhysicalSize += this._physicalSizes[pidx]; 3487 newPhysicalSize += this._physicalSizes[pidx];
3394 this._physicalAverageCount += this._physicalSizes[pidx] ? 1 : 0; 3488 this._physicalAverageCount += this._physicalSizes[pidx] ? 1 : 0;
3395 3489
3396 }, itemSet); 3490 }, itemSet);
3397 3491
3398 this._physicalSize = this._physicalSize + newPhysicalSize - oldPhysicalSiz e; 3492 this._viewportHeight = this._scrollTargetHeight;
3399 this._viewportSize = this._scrollTargetHeight; 3493 if (this.grid) {
3494 this._updateGridMetrics();
3495 this._physicalSize = Math.ceil(this._physicalCount / this._itemsPerRow) * this._rowHeight;
3496 } else {
3497 this._physicalSize = this._physicalSize + newPhysicalSize - oldPhysicalS ize;
3498 }
3400 3499
3401 // update the average if we measured something 3500 // update the average if we measured something
3402 if (this._physicalAverageCount !== prevAvgCount) { 3501 if (this._physicalAverageCount !== prevAvgCount) {
3403 this._physicalAverage = Math.round( 3502 this._physicalAverage = Math.round(
3404 ((prevPhysicalAvg * prevAvgCount) + newPhysicalSize) / 3503 ((prevPhysicalAvg * prevAvgCount) + newPhysicalSize) /
3405 this._physicalAverageCount); 3504 this._physicalAverageCount);
3406 } 3505 }
3407 }, 3506 },
3408 3507
3508 _updateGridMetrics: function() {
3509 this._viewportWidth = this._scrollTargetWidth;
3510 // Set item width to the value of the _physicalItems offsetWidth
3511 this._itemWidth = this._physicalCount > 0 ? this._physicalItems[0].offsetW idth : DEFAULT_GRID_SIZE;
3512 // Set row height to the value of the _physicalItems offsetHeight
3513 this._rowHeight = this._physicalCount > 0 ? this._physicalItems[0].offsetH eight : DEFAULT_GRID_SIZE;
3514 // If in grid mode compute how many items with exist in each row
3515 this._itemsPerRow = this._itemWidth ? Math.floor(this._viewportWidth / thi s._itemWidth) : this._itemsPerRow;
3516 },
3517
3409 /** 3518 /**
3410 * Updates the position of the physical items. 3519 * Updates the position of the physical items.
3411 */ 3520 */
3412 _positionItems: function() { 3521 _positionItems: function() {
3413 this._adjustScrollPosition(); 3522 this._adjustScrollPosition();
3414 3523
3415 var y = this._physicalTop; 3524 var y = this._physicalTop;
3416 3525
3417 this._iterateItems(function(pidx) { 3526 if (this.grid) {
3418 this.translate3d(0, y + 'px', 0, this._physicalItems[pidx]); 3527 var totalItemWidth = this._itemsPerRow * this._itemWidth;
3419 y += this._physicalSizes[pidx]; 3528 var rowOffset = (this._viewportWidth - totalItemWidth) / 2;
3420 }); 3529
3530 this._iterateItems(function(pidx, vidx) {
3531
3532 var modulus = vidx % this._itemsPerRow;
3533 var x = Math.floor((modulus * this._itemWidth) + rowOffset);
3534
3535 this.translate3d(x + 'px', y + 'px', 0, this._physicalItems[pidx]);
3536
3537 if (this._shouldRenderNextRow(vidx)) {
3538 y += this._rowHeight;
3539 }
3540
3541 });
3542 } else {
3543 this._iterateItems(function(pidx, vidx) {
3544
3545 this.translate3d(0, y + 'px', 0, this._physicalItems[pidx]);
3546 y += this._physicalSizes[pidx];
3547
3548 });
3549 }
3550 },
3551
3552 _getPhysicalSizeIncrement: function(pidx) {
3553 if (!this.grid) {
3554 return this._physicalSizes[pidx];
3555 }
3556 if (this._computeVidx(pidx) % this._itemsPerRow !== this._itemsPerRow - 1) {
3557 return 0;
3558 }
3559 return this._rowHeight;
3421 }, 3560 },
3422 3561
3423 /** 3562 /**
3563 * Returns, based on the current index,
3564 * whether or not the next index will need
3565 * to be rendered on a new row.
3566 *
3567 * @param {number} vidx Virtual index
3568 * @return {boolean}
3569 */
3570 _shouldRenderNextRow: function(vidx) {
3571 return vidx % this._itemsPerRow === this._itemsPerRow - 1;
3572 },
3573
3574 /**
3424 * Adjusts the scroll position when it was overestimated. 3575 * Adjusts the scroll position when it was overestimated.
3425 */ 3576 */
3426 _adjustScrollPosition: function() { 3577 _adjustScrollPosition: function() {
3427 var deltaHeight = this._virtualStart === 0 ? this._physicalTop : 3578 var deltaHeight = this._virtualStart === 0 ? this._physicalTop :
3428 Math.min(this._scrollPosition + this._physicalTop, 0); 3579 Math.min(this._scrollPosition + this._physicalTop, 0);
3429 3580
3430 if (deltaHeight) { 3581 if (deltaHeight) {
3431 this._physicalTop = this._physicalTop - deltaHeight; 3582 this._physicalTop = this._physicalTop - deltaHeight;
3432 // juking scroll position during interial scrolling on iOS is no bueno 3583 // juking scroll position during interial scrolling on iOS is no bueno
3433 if (!IOS_TOUCH_SCROLLING) { 3584 if (!IOS_TOUCH_SCROLLING) {
(...skipping 11 matching lines...) Expand all
3445 this._scrollPosition = this._scrollTop; 3596 this._scrollPosition = this._scrollTop;
3446 } 3597 }
3447 }, 3598 },
3448 3599
3449 /** 3600 /**
3450 * Sets the scroll height, that's the height of the content, 3601 * Sets the scroll height, that's the height of the content,
3451 * 3602 *
3452 * @param {boolean=} forceUpdate If true, updates the height no matter what. 3603 * @param {boolean=} forceUpdate If true, updates the height no matter what.
3453 */ 3604 */
3454 _updateScrollerSize: function(forceUpdate) { 3605 _updateScrollerSize: function(forceUpdate) {
3455 this._estScrollHeight = (this._physicalBottom + 3606 if (this.grid) {
3456 Math.max(this._virtualCount - this._physicalCount - this._virtualStart , 0) * this._physicalAverage); 3607 this._estScrollHeight = this._virtualRowCount * this._rowHeight;
3608 } else {
3609 this._estScrollHeight = (this._physicalBottom +
3610 Math.max(this._virtualCount - this._physicalCount - this._virtualSta rt, 0) * this._physicalAverage);
3611 }
3457 3612
3458 forceUpdate = forceUpdate || this._scrollHeight === 0; 3613 forceUpdate = forceUpdate || this._scrollHeight === 0;
3459 forceUpdate = forceUpdate || this._scrollPosition >= this._estScrollHeight - this._physicalSize; 3614 forceUpdate = forceUpdate || this._scrollPosition >= this._estScrollHeight - this._physicalSize;
3615 forceUpdate = forceUpdate || this.grid && this.$.items.style.height < this ._estScrollHeight;
3460 3616
3461 // amortize height adjustment, so it won't trigger repaints very often 3617 // amortize height adjustment, so it won't trigger repaints very often
3462 if (forceUpdate || Math.abs(this._estScrollHeight - this._scrollHeight) >= this._optPhysicalSize) { 3618 if (forceUpdate || Math.abs(this._estScrollHeight - this._scrollHeight) >= this._optPhysicalSize) {
3463 this.$.items.style.height = this._estScrollHeight + 'px'; 3619 this.$.items.style.height = this._estScrollHeight + 'px';
3464 this._scrollHeight = this._estScrollHeight; 3620 this._scrollHeight = this._estScrollHeight;
3465 } 3621 }
3466 }, 3622 },
3467 /** 3623 /**
3468 * Scroll to a specific item in the virtual list regardless 3624 * Scroll to a specific item in the virtual list regardless
3469 * of the physical items in the DOM tree. 3625 * of the physical items in the DOM tree.
3470 * 3626 *
3471 * @method scrollToIndex 3627 * @method scrollToIndex
3472 * @param {number} idx The index of the item 3628 * @param {number} idx The index of the item
3473 */ 3629 */
3474 scrollToIndex: function(idx) { 3630 scrollToIndex: function(idx) {
3475 if (typeof idx !== 'number') { 3631 if (typeof idx !== 'number') {
3476 return; 3632 return;
3477 } 3633 }
3478 3634
3479 Polymer.dom.flush(); 3635 Polymer.dom.flush();
3480 3636
3481 idx = Math.min(Math.max(idx, 0), this._virtualCount-1); 3637 idx = Math.min(Math.max(idx, 0), this._virtualCount-1);
3482 // update the virtual start only when needed 3638 // update the virtual start only when needed
3483 if (!this._isIndexRendered(idx) || idx >= this._maxVirtualStart) { 3639 if (!this._isIndexRendered(idx) || idx >= this._maxVirtualStart) {
3484 this._virtualStart = idx - 1; 3640 this._virtualStart = this.grid ? (idx - this._itemsPerRow * 2) : (idx - 1);
3485 } 3641 }
3486 // manage focus 3642 // manage focus
3487 this._manageFocus(); 3643 this._manageFocus();
3488 // assign new models 3644 // assign new models
3489 this._assignModels(); 3645 this._assignModels();
3490 // measure the new sizes 3646 // measure the new sizes
3491 this._updateMetrics(); 3647 this._updateMetrics();
3648
3492 // estimate new physical offset 3649 // estimate new physical offset
3493 this._physicalTop = this._virtualStart * this._physicalAverage; 3650 var estPhysicalTop = Math.floor(this._virtualStart / this._itemsPerRow) * this._physicalAverage;
3651 this._physicalTop = estPhysicalTop;
3494 3652
3495 var currentTopItem = this._physicalStart; 3653 var currentTopItem = this._physicalStart;
3496 var currentVirtualItem = this._virtualStart; 3654 var currentVirtualItem = this._virtualStart;
3497 var targetOffsetTop = 0; 3655 var targetOffsetTop = 0;
3498 var hiddenContentSize = this._hiddenContentSize; 3656 var hiddenContentSize = this._hiddenContentSize;
3499 3657
3500 // scroll to the item as much as we can 3658 // scroll to the item as much as we can
3501 while (currentVirtualItem < idx && targetOffsetTop < hiddenContentSize) { 3659 while (currentVirtualItem < idx && targetOffsetTop <= hiddenContentSize) {
3502 targetOffsetTop = targetOffsetTop + this._physicalSizes[currentTopItem]; 3660 targetOffsetTop = targetOffsetTop + this._getPhysicalSizeIncrement(curre ntTopItem);
3503 currentTopItem = (currentTopItem + 1) % this._physicalCount; 3661 currentTopItem = (currentTopItem + 1) % this._physicalCount;
3504 currentVirtualItem++; 3662 currentVirtualItem++;
3505 } 3663 }
3506 // update the scroller size 3664 // update the scroller size
3507 this._updateScrollerSize(true); 3665 this._updateScrollerSize(true);
3508 // update the position of the items 3666 // update the position of the items
3509 this._positionItems(); 3667 this._positionItems();
3510 // set the new scroll position 3668 // set the new scroll position
3511 this._resetScrollPosition(this._physicalTop + this._scrollerPaddingTop + t argetOffsetTop); 3669 this._resetScrollPosition(this._physicalTop + this._scrollerPaddingTop + t argetOffsetTop);
3512 // increase the pool of physical items if needed 3670 // increase the pool of physical items if needed
(...skipping 10 matching lines...) Expand all
3523 this._physicalAverage = 0; 3681 this._physicalAverage = 0;
3524 this._physicalAverageCount = 0; 3682 this._physicalAverageCount = 0;
3525 }, 3683 },
3526 3684
3527 /** 3685 /**
3528 * A handler for the `iron-resize` event triggered by `IronResizableBehavior ` 3686 * A handler for the `iron-resize` event triggered by `IronResizableBehavior `
3529 * when the element is resized. 3687 * when the element is resized.
3530 */ 3688 */
3531 _resizeHandler: function() { 3689 _resizeHandler: function() {
3532 // iOS fires the resize event when the address bar slides up 3690 // iOS fires the resize event when the address bar slides up
3533 if (IOS && Math.abs(this._viewportSize - this._scrollTargetHeight) < 100) { 3691 if (IOS && Math.abs(this._viewportHeight - this._scrollTargetHeight) < 100 ) {
3534 return; 3692 return;
3535 } 3693 }
3536 // In Desktop Safari 9.0.3, if the scroll bars are always shown, 3694 // In Desktop Safari 9.0.3, if the scroll bars are always shown,
3537 // changing the scroll position from a resize handler would result in 3695 // changing the scroll position from a resize handler would result in
3538 // the scroll position being reset. Waiting 1ms fixes the issue. 3696 // the scroll position being reset. Waiting 1ms fixes the issue.
3539 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', 3697 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', function() {
3540 function() { 3698 this.updateViewportBoundaries();
3541 this._render(); 3699 this._render();
3542 3700
3543 if (this._itemsRendered && this._physicalItems && this._isVisible) { 3701 if (this._itemsRendered && this._physicalItems && this._isVisible) {
3544 this._resetAverage(); 3702 this._resetAverage();
3545 this.updateViewportBoundaries(); 3703 this.scrollToIndex(this.firstVisibleIndex);
3546 this.scrollToIndex(this.firstVisibleIndex); 3704 }
3547 } 3705 }.bind(this), 1));
3548 }.bind(this), 1));
3549 }, 3706 },
3550 3707
3551 _getModelFromItem: function(item) { 3708 _getModelFromItem: function(item) {
3552 var key = this._collection.getKey(item); 3709 var key = this._collection.getKey(item);
3553 var pidx = this._physicalIndexForKey[key]; 3710 var pidx = this._physicalIndexForKey[key];
3554 3711
3555 if (pidx != null) { 3712 if (pidx != null) {
3556 return this._physicalItems[pidx]._templateInstance; 3713 return this._physicalItems[pidx]._templateInstance;
3557 } 3714 }
3558 return null; 3715 return null;
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
3849 if (hasOffscreenFocusedItem && !this._offscreenFocusedItem) { 4006 if (hasOffscreenFocusedItem && !this._offscreenFocusedItem) {
3850 this._update(); 4007 this._update();
3851 } 4008 }
3852 } 4009 }
3853 }, 4010 },
3854 4011
3855 _didMoveUp: function() { 4012 _didMoveUp: function() {
3856 this._focusPhysicalItem(this._focusedIndex - 1); 4013 this._focusPhysicalItem(this._focusedIndex - 1);
3857 }, 4014 },
3858 4015
3859 _didMoveDown: function() { 4016 _didMoveDown: function(e) {
4017 // disable scroll when pressing the down key
4018 e.detail.keyboardEvent.preventDefault();
3860 this._focusPhysicalItem(this._focusedIndex + 1); 4019 this._focusPhysicalItem(this._focusedIndex + 1);
3861 }, 4020 },
3862 4021
3863 _didEnter: function(e) { 4022 _didEnter: function(e) {
3864 this._focusPhysicalItem(this._focusedIndex); 4023 this._focusPhysicalItem(this._focusedIndex);
3865 this._selectionHandler(e.detail.keyboardEvent); 4024 this._selectionHandler(e.detail.keyboardEvent);
3866 } 4025 }
3867 }); 4026 });
3868 4027
3869 })(); 4028 })();
(...skipping 3294 matching lines...) Expand 10 before | Expand all | Expand 10 after
7164 * Given a KeyboardEvent, this method will focus the appropriate item in the 7323 * Given a KeyboardEvent, this method will focus the appropriate item in the
7165 * menu (if there is a relevant item, and it is possible to focus it). 7324 * menu (if there is a relevant item, and it is possible to focus it).
7166 * 7325 *
7167 * @param {KeyboardEvent} event A KeyboardEvent. 7326 * @param {KeyboardEvent} event A KeyboardEvent.
7168 */ 7327 */
7169 _focusWithKeyboardEvent: function(event) { 7328 _focusWithKeyboardEvent: function(event) {
7170 for (var i = 0, item; item = this.items[i]; i++) { 7329 for (var i = 0, item; item = this.items[i]; i++) {
7171 var attr = this.attrForItemTitle || 'textContent'; 7330 var attr = this.attrForItemTitle || 'textContent';
7172 var title = item[attr] || item.getAttribute(attr); 7331 var title = item[attr] || item.getAttribute(attr);
7173 7332
7174 if (title && title.trim().charAt(0).toLowerCase() === String.fromCharCod e(event.keyCode).toLowerCase()) { 7333 if (!item.hasAttribute('disabled') && title &&
7334 title.trim().charAt(0).toLowerCase() === String.fromCharCode(event.k eyCode).toLowerCase()) {
7175 this._setFocusedItem(item); 7335 this._setFocusedItem(item);
7176 break; 7336 break;
7177 } 7337 }
7178 } 7338 }
7179 }, 7339 },
7180 7340
7181 /** 7341 /**
7182 * Focuses the previous item (relative to the currently focused item) in the 7342 * Focuses the previous item (relative to the currently focused item) in the
7183 * menu. 7343 * menu, disabled items will be skipped.
7184 */ 7344 */
7185 _focusPrevious: function() { 7345 _focusPrevious: function() {
7186 var length = this.items.length; 7346 var length = this.items.length;
7187 var index = (Number(this.indexOf(this.focusedItem)) - 1 + length) % length ; 7347 var curFocusIndex = Number(this.indexOf(this.focusedItem));
7188 this._setFocusedItem(this.items[index]); 7348 for (var i = 1; i < length; i++) {
7349 var item = this.items[(curFocusIndex - i + length) % length];
7350 if (!item.hasAttribute('disabled')) {
7351 this._setFocusedItem(item);
7352 return;
7353 }
7354 }
7189 }, 7355 },
7190 7356
7191 /** 7357 /**
7192 * Focuses the next item (relative to the currently focused item) in the 7358 * Focuses the next item (relative to the currently focused item) in the
7193 * menu. 7359 * menu, disabled items will be skipped.
7194 */ 7360 */
7195 _focusNext: function() { 7361 _focusNext: function() {
7196 var index = (Number(this.indexOf(this.focusedItem)) + 1) % this.items.leng th; 7362 var length = this.items.length;
7197 this._setFocusedItem(this.items[index]); 7363 var curFocusIndex = Number(this.indexOf(this.focusedItem));
7364 for (var i = 1; i < length; i++) {
7365 var item = this.items[(curFocusIndex + i) % length];
7366 if (!item.hasAttribute('disabled')) {
7367 this._setFocusedItem(item);
7368 return;
7369 }
7370 }
7198 }, 7371 },
7199 7372
7200 /** 7373 /**
7201 * Mutates items in the menu based on provided selection details, so that 7374 * Mutates items in the menu based on provided selection details, so that
7202 * all items correctly reflect selection state. 7375 * all items correctly reflect selection state.
7203 * 7376 *
7204 * @param {Element} item An item in the menu. 7377 * @param {Element} item An item in the menu.
7205 * @param {boolean} isSelected True if the item should be shown in a 7378 * @param {boolean} isSelected True if the item should be shown in a
7206 * selected state, otherwise false. 7379 * selected state, otherwise false.
7207 */ 7380 */
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
7296 this._defaultFocusAsync = this.async(function() { 7469 this._defaultFocusAsync = this.async(function() {
7297 // focus the selected item when the menu receives focus, or the first it em 7470 // focus the selected item when the menu receives focus, or the first it em
7298 // if no item is selected 7471 // if no item is selected
7299 var selectedItem = this.multi ? (this.selectedItems && this.selectedItem s[0]) : this.selectedItem; 7472 var selectedItem = this.multi ? (this.selectedItems && this.selectedItem s[0]) : this.selectedItem;
7300 7473
7301 this._setFocusedItem(null); 7474 this._setFocusedItem(null);
7302 7475
7303 if (selectedItem) { 7476 if (selectedItem) {
7304 this._setFocusedItem(selectedItem); 7477 this._setFocusedItem(selectedItem);
7305 } else if (this.items[0]) { 7478 } else if (this.items[0]) {
7306 this._setFocusedItem(this.items[0]); 7479 // We find the first none-disabled item (if one exists)
7480 this._focusNext();
7307 } 7481 }
7308 }); 7482 });
7309 }, 7483 },
7310 7484
7311 /** 7485 /**
7312 * Handler that is called when the up key is pressed. 7486 * Handler that is called when the up key is pressed.
7313 * 7487 *
7314 * @param {CustomEvent} event A key combination event. 7488 * @param {CustomEvent} event A key combination event.
7315 */ 7489 */
7316 _onUpKey: function(event) { 7490 _onUpKey: function(event) {
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
7664 document.addEventListener('focus', this._onCaptureFocus.bind(this), true); 7838 document.addEventListener('focus', this._onCaptureFocus.bind(this), true);
7665 document.addEventListener('keydown', this._onCaptureKeyDown.bind(this), true ); 7839 document.addEventListener('keydown', this._onCaptureKeyDown.bind(this), true );
7666 }; 7840 };
7667 7841
7668 Polymer.IronOverlayManagerClass.prototype = { 7842 Polymer.IronOverlayManagerClass.prototype = {
7669 7843
7670 constructor: Polymer.IronOverlayManagerClass, 7844 constructor: Polymer.IronOverlayManagerClass,
7671 7845
7672 /** 7846 /**
7673 * The shared backdrop element. 7847 * The shared backdrop element.
7674 * @type {Element} backdropElement 7848 * @type {!Element} backdropElement
7675 */ 7849 */
7676 get backdropElement() { 7850 get backdropElement() {
7677 if (!this._backdropElement) { 7851 if (!this._backdropElement) {
7678 this._backdropElement = document.createElement('iron-overlay-backdrop'); 7852 this._backdropElement = document.createElement('iron-overlay-backdrop');
7679 } 7853 }
7680 return this._backdropElement; 7854 return this._backdropElement;
7681 }, 7855 },
7682 7856
7683 /** 7857 /**
7684 * The deepest active element. 7858 * The deepest active element.
7685 * @type {Element} activeElement the active element 7859 * @type {!Element} activeElement the active element
7686 */ 7860 */
7687 get deepActiveElement() { 7861 get deepActiveElement() {
7688 // document.activeElement can be null 7862 // document.activeElement can be null
7689 // https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement 7863 // https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement
7690 // In case of null, default it to document.body. 7864 // In case of null, default it to document.body.
7691 var active = document.activeElement || document.body; 7865 var active = document.activeElement || document.body;
7692 while (active.root && Polymer.dom(active.root).activeElement) { 7866 while (active.root && Polymer.dom(active.root).activeElement) {
7693 active = Polymer.dom(active.root).activeElement; 7867 active = Polymer.dom(active.root).activeElement;
7694 } 7868 }
7695 return active; 7869 return active;
7696 }, 7870 },
7697 7871
7698 /** 7872 /**
7699 * Brings the overlay at the specified index to the front. 7873 * Brings the overlay at the specified index to the front.
7700 * @param {number} i 7874 * @param {number} i
7701 * @private 7875 * @private
7702 */ 7876 */
7703 _bringOverlayAtIndexToFront: function(i) { 7877 _bringOverlayAtIndexToFront: function(i) {
7704 var overlay = this._overlays[i]; 7878 var overlay = this._overlays[i];
7879 if (!overlay) {
7880 return;
7881 }
7705 var lastI = this._overlays.length - 1; 7882 var lastI = this._overlays.length - 1;
7883 var currentOverlay = this._overlays[lastI];
7706 // Ensure always-on-top overlay stays on top. 7884 // Ensure always-on-top overlay stays on top.
7707 if (!overlay.alwaysOnTop && this._overlays[lastI].alwaysOnTop) { 7885 if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay) ) {
7708 lastI--; 7886 lastI--;
7709 } 7887 }
7710 // If already the top element, return. 7888 // If already the top element, return.
7711 if (!overlay || i >= lastI) { 7889 if (i >= lastI) {
7712 return; 7890 return;
7713 } 7891 }
7714 // Update z-index to be on top. 7892 // Update z-index to be on top.
7715 var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ); 7893 var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ);
7716 if (this._getZ(overlay) <= minimumZ) { 7894 if (this._getZ(overlay) <= minimumZ) {
7717 this._applyOverlayZ(overlay, minimumZ); 7895 this._applyOverlayZ(overlay, minimumZ);
7718 } 7896 }
7719 7897
7720 // Shift other overlays behind the new on top. 7898 // Shift other overlays behind the new on top.
7721 while (i < lastI) { 7899 while (i < lastI) {
7722 this._overlays[i] = this._overlays[i + 1]; 7900 this._overlays[i] = this._overlays[i + 1];
7723 i++; 7901 i++;
7724 } 7902 }
7725 this._overlays[lastI] = overlay; 7903 this._overlays[lastI] = overlay;
7726 }, 7904 },
7727 7905
7728 /** 7906 /**
7729 * Adds the overlay and updates its z-index if it's opened, or removes it if it's closed. 7907 * Adds the overlay and updates its z-index if it's opened, or removes it if it's closed.
7730 * Also updates the backdrop z-index. 7908 * Also updates the backdrop z-index.
7731 * @param {Element} overlay 7909 * @param {!Element} overlay
7732 */ 7910 */
7733 addOrRemoveOverlay: function(overlay) { 7911 addOrRemoveOverlay: function(overlay) {
7734 if (overlay.opened) { 7912 if (overlay.opened) {
7735 this.addOverlay(overlay); 7913 this.addOverlay(overlay);
7736 } else { 7914 } else {
7737 this.removeOverlay(overlay); 7915 this.removeOverlay(overlay);
7738 } 7916 }
7739 this.trackBackdrop(); 7917 this.trackBackdrop();
7740 }, 7918 },
7741 7919
7742 /** 7920 /**
7743 * Tracks overlays for z-index and focus management. 7921 * Tracks overlays for z-index and focus management.
7744 * Ensures the last added overlay with always-on-top remains on top. 7922 * Ensures the last added overlay with always-on-top remains on top.
7745 * @param {Element} overlay 7923 * @param {!Element} overlay
7746 */ 7924 */
7747 addOverlay: function(overlay) { 7925 addOverlay: function(overlay) {
7748 var i = this._overlays.indexOf(overlay); 7926 var i = this._overlays.indexOf(overlay);
7749 if (i >= 0) { 7927 if (i >= 0) {
7750 this._bringOverlayAtIndexToFront(i); 7928 this._bringOverlayAtIndexToFront(i);
7751 return; 7929 return;
7752 } 7930 }
7753 var insertionIndex = this._overlays.length; 7931 var insertionIndex = this._overlays.length;
7754 var currentOverlay = this._overlays[insertionIndex - 1]; 7932 var currentOverlay = this._overlays[insertionIndex - 1];
7755 var minimumZ = Math.max(this._getZ(currentOverlay), this._minimumZ); 7933 var minimumZ = Math.max(this._getZ(currentOverlay), this._minimumZ);
7756 var newZ = this._getZ(overlay); 7934 var newZ = this._getZ(overlay);
7757 7935
7758 // Ensure always-on-top overlay stays on top. 7936 // Ensure always-on-top overlay stays on top.
7759 if (currentOverlay && currentOverlay.alwaysOnTop && !overlay.alwaysOnTop) { 7937 if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay) ) {
7760 // This bumps the z-index of +2. 7938 // This bumps the z-index of +2.
7761 this._applyOverlayZ(currentOverlay, minimumZ); 7939 this._applyOverlayZ(currentOverlay, minimumZ);
7762 insertionIndex--; 7940 insertionIndex--;
7763 // Update minimumZ to match previous overlay's z-index. 7941 // Update minimumZ to match previous overlay's z-index.
7764 var previousOverlay = this._overlays[insertionIndex - 1]; 7942 var previousOverlay = this._overlays[insertionIndex - 1];
7765 minimumZ = Math.max(this._getZ(previousOverlay), this._minimumZ); 7943 minimumZ = Math.max(this._getZ(previousOverlay), this._minimumZ);
7766 } 7944 }
7767 7945
7768 // Update z-index and insert overlay. 7946 // Update z-index and insert overlay.
7769 if (newZ <= minimumZ) { 7947 if (newZ <= minimumZ) {
7770 this._applyOverlayZ(overlay, minimumZ); 7948 this._applyOverlayZ(overlay, minimumZ);
7771 } 7949 }
7772 this._overlays.splice(insertionIndex, 0, overlay); 7950 this._overlays.splice(insertionIndex, 0, overlay);
7773 7951
7774 // Get focused node. 7952 // Get focused node.
7775 var element = this.deepActiveElement; 7953 var element = this.deepActiveElement;
7776 overlay.restoreFocusNode = this._overlayParent(element) ? null : element; 7954 overlay.restoreFocusNode = this._overlayParent(element) ? null : element;
7777 }, 7955 },
7778 7956
7779 /** 7957 /**
7780 * @param {Element} overlay 7958 * @param {!Element} overlay
7781 */ 7959 */
7782 removeOverlay: function(overlay) { 7960 removeOverlay: function(overlay) {
7783 var i = this._overlays.indexOf(overlay); 7961 var i = this._overlays.indexOf(overlay);
7784 if (i === -1) { 7962 if (i === -1) {
7785 return; 7963 return;
7786 } 7964 }
7787 this._overlays.splice(i, 1); 7965 this._overlays.splice(i, 1);
7788 7966
7789 var node = overlay.restoreFocusOnClose ? overlay.restoreFocusNode : null; 7967 var node = overlay.restoreFocusOnClose ? overlay.restoreFocusNode : null;
7790 overlay.restoreFocusNode = null; 7968 overlay.restoreFocusNode = null;
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
7888 // Check if is a number 8066 // Check if is a number
7889 // Number.isNaN not supported in IE 10+ 8067 // Number.isNaN not supported in IE 10+
7890 if (z1 === z1) { 8068 if (z1 === z1) {
7891 z = z1; 8069 z = z1;
7892 } 8070 }
7893 } 8071 }
7894 return z; 8072 return z;
7895 }, 8073 },
7896 8074
7897 /** 8075 /**
7898 * @param {Element} element 8076 * @param {!Element} element
7899 * @param {number|string} z 8077 * @param {number|string} z
7900 * @private 8078 * @private
7901 */ 8079 */
7902 _setZ: function(element, z) { 8080 _setZ: function(element, z) {
7903 element.style.zIndex = z; 8081 element.style.zIndex = z;
7904 }, 8082 },
7905 8083
7906 /** 8084 /**
7907 * @param {Element} overlay 8085 * @param {!Element} overlay
7908 * @param {number} aboveZ 8086 * @param {number} aboveZ
7909 * @private 8087 * @private
7910 */ 8088 */
7911 _applyOverlayZ: function(overlay, aboveZ) { 8089 _applyOverlayZ: function(overlay, aboveZ) {
7912 this._setZ(overlay, aboveZ + 2); 8090 this._setZ(overlay, aboveZ + 2);
7913 }, 8091 },
7914 8092
7915 /** 8093 /**
7916 * Returns the overlay containing the provided node. If the node is an overl ay, 8094 * Returns the overlay containing the provided node. If the node is an overl ay,
7917 * it returns the node. 8095 * it returns the node.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
7977 */ 8155 */
7978 _onCaptureKeyDown: function(event) { 8156 _onCaptureKeyDown: function(event) {
7979 var overlay = /** @type {?} */ (this.currentOverlay()); 8157 var overlay = /** @type {?} */ (this.currentOverlay());
7980 if (overlay) { 8158 if (overlay) {
7981 if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'esc')) { 8159 if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'esc')) {
7982 overlay._onCaptureEsc(event); 8160 overlay._onCaptureEsc(event);
7983 } else if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'tab')) { 8161 } else if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'tab')) {
7984 overlay._onCaptureTab(event); 8162 overlay._onCaptureTab(event);
7985 } 8163 }
7986 } 8164 }
8165 },
8166
8167 /**
8168 * Returns if the overlay1 should be behind overlay2.
8169 * @param {!Element} overlay1
8170 * @param {!Element} overlay2
8171 * @return {boolean}
8172 * @private
8173 */
8174 _shouldBeBehindOverlay: function(overlay1, overlay2) {
8175 var o1 = /** @type {?} */ (overlay1);
8176 var o2 = /** @type {?} */ (overlay2);
8177 return !o1.alwaysOnTop && o2.alwaysOnTop;
7987 } 8178 }
7988 }; 8179 };
7989 8180
7990 Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass(); 8181 Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass();
7991 (function() { 8182 (function() {
7992 8183
7993 Polymer({ 8184 Polymer({
7994 8185
7995 is: 'iron-overlay-backdrop', 8186 is: 'iron-overlay-backdrop',
7996 8187
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
8376 if (!this._overlaySetup) { 8567 if (!this._overlaySetup) {
8377 return; 8568 return;
8378 } 8569 }
8379 8570
8380 this._manager.addOrRemoveOverlay(this); 8571 this._manager.addOrRemoveOverlay(this);
8381 8572
8382 this.__isAnimating = true; 8573 this.__isAnimating = true;
8383 8574
8384 // requestAnimationFrame for non-blocking rendering 8575 // requestAnimationFrame for non-blocking rendering
8385 if (this.__openChangedAsync) { 8576 if (this.__openChangedAsync) {
8386 cancelAnimationFrame(this.__openChangedAsync); 8577 window.cancelAnimationFrame(this.__openChangedAsync);
8387 } 8578 }
8388 if (this.opened) { 8579 if (this.opened) {
8389 if (this.withBackdrop) { 8580 if (this.withBackdrop) {
8390 this.backdropElement.prepare(); 8581 this.backdropElement.prepare();
8391 } 8582 }
8392 this.__openChangedAsync = requestAnimationFrame(function() { 8583 this.__openChangedAsync = window.requestAnimationFrame(function() {
8393 this.__openChangedAsync = null; 8584 this.__openChangedAsync = null;
8394 this._prepareRenderOpened(); 8585 this._prepareRenderOpened();
8395 this._renderOpened(); 8586 this._renderOpened();
8396 }.bind(this)); 8587 }.bind(this));
8397 } else { 8588 } else {
8398 this._renderClosed(); 8589 this._renderClosed();
8399 } 8590 }
8400 }, 8591 },
8401 8592
8402 _canceledChanged: function() { 8593 _canceledChanged: function() {
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
8593 this._focusedChild = nodeToSet; 8784 this._focusedChild = nodeToSet;
8594 } 8785 }
8595 }, 8786 },
8596 8787
8597 /** 8788 /**
8598 * Refits if the overlay is opened and not animating. 8789 * Refits if the overlay is opened and not animating.
8599 * @protected 8790 * @protected
8600 */ 8791 */
8601 _onIronResize: function() { 8792 _onIronResize: function() {
8602 if (this.__onIronResizeAsync) { 8793 if (this.__onIronResizeAsync) {
8603 cancelAnimationFrame(this.__onIronResizeAsync); 8794 window.cancelAnimationFrame(this.__onIronResizeAsync);
8604 this.__onIronResizeAsync = null; 8795 this.__onIronResizeAsync = null;
8605 } 8796 }
8606 if (this.opened && !this.__isAnimating) { 8797 if (this.opened && !this.__isAnimating) {
8607 this.__onIronResizeAsync = requestAnimationFrame(function() { 8798 this.__onIronResizeAsync = window.requestAnimationFrame(function() {
8608 this.__onIronResizeAsync = null; 8799 this.__onIronResizeAsync = null;
8609 this.refit(); 8800 this.refit();
8610 }.bind(this)); 8801 }.bind(this));
8611 } 8802 }
8612 }, 8803 },
8613 8804
8614 /** 8805 /**
8615 * Will call notifyResize if overlay is opened. 8806 * Will call notifyResize if overlay is opened.
8616 * Can be overridden in order to avoid multiple observers on the same node. 8807 * Can be overridden in order to avoid multiple observers on the same node.
8617 * @protected 8808 * @protected
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
8668 return { 8859 return {
8669 duration: 500, 8860 duration: 500,
8670 easing: 'cubic-bezier(0.4, 0, 0.2, 1)', 8861 easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
8671 fill: 'both' 8862 fill: 'both'
8672 } 8863 }
8673 } 8864 }
8674 } 8865 }
8675 8866
8676 }, 8867 },
8677 8868
8678 registered: function() { 8869 /**
8679 new Polymer.IronMeta({type: 'animation', key: this.is, value: this.constru ctor}); 8870 * Can be used to determine that elements implement this behavior.
8680 }, 8871 */
8872 isNeonAnimation: true,
8681 8873
8682 /** 8874 /**
8683 * Do any animation configuration here. 8875 * Do any animation configuration here.
8684 */ 8876 */
8685 // configure: function(config) { 8877 // configure: function(config) {
8686 // }, 8878 // },
8687 8879
8688 /** 8880 /**
8689 * Returns the animation timing by mixing in properties from `config` to the defaults defined 8881 * Returns the animation timing by mixing in properties from `config` to the defaults defined
8690 * by the animation. 8882 * by the animation.
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
8889 }; 9081 };
8890 /** 9082 /**
8891 * `Polymer.NeonAnimationRunnerBehavior` adds a method to run animations. 9083 * `Polymer.NeonAnimationRunnerBehavior` adds a method to run animations.
8892 * 9084 *
8893 * @polymerBehavior Polymer.NeonAnimationRunnerBehavior 9085 * @polymerBehavior Polymer.NeonAnimationRunnerBehavior
8894 */ 9086 */
8895 Polymer.NeonAnimationRunnerBehaviorImpl = { 9087 Polymer.NeonAnimationRunnerBehaviorImpl = {
8896 9088
8897 properties: { 9089 properties: {
8898 9090
8899 _animationMeta: {
8900 type: Object,
8901 value: function() {
8902 return new Polymer.IronMeta({type: 'animation'});
8903 }
8904 },
8905
8906 /** @type {?Object} */ 9091 /** @type {?Object} */
8907 _player: { 9092 _player: {
8908 type: Object 9093 type: Object
8909 } 9094 }
8910 9095
8911 }, 9096 },
8912 9097
8913 _configureAnimationEffects: function(allConfigs) { 9098 _configureAnimationEffects: function(allConfigs) {
8914 var allAnimations = []; 9099 var allAnimations = [];
8915 if (allConfigs.length > 0) { 9100 if (allConfigs.length > 0) {
8916 for (var config, index = 0; config = allConfigs[index]; index++) { 9101 for (var config, index = 0; config = allConfigs[index]; index++) {
8917 var animationConstructor = this._animationMeta.byKey(config.name); 9102 var animation = document.createElement(config.name);
8918 if (animationConstructor) { 9103 // is this element actually a neon animation?
8919 var animation = animationConstructor && new animationConstructor(); 9104 if (animation.isNeonAnimation) {
8920 var effect = animation.configure(config); 9105 var effect = animation.configure(config);
8921 if (effect) { 9106 if (effect) {
8922 allAnimations.push({ 9107 allAnimations.push({
8923 animation: animation, 9108 animation: animation,
8924 config: config, 9109 config: config,
8925 effect: effect 9110 effect: effect
8926 }); 9111 });
8927 } 9112 }
8928 } else { 9113 } else {
8929 console.warn(this.is + ':', config.name, 'not found!'); 9114 console.warn(this.is + ':', config.name, 'not found!');
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
9338 9523
9339 listeners: { 9524 listeners: {
9340 'neon-animation-finish': '_onNeonAnimationFinish' 9525 'neon-animation-finish': '_onNeonAnimationFinish'
9341 }, 9526 },
9342 9527
9343 observers: [ 9528 observers: [
9344 '_updateOverlayPosition(positionTarget, verticalAlign, horizontalAlign , verticalOffset, horizontalOffset)' 9529 '_updateOverlayPosition(positionTarget, verticalAlign, horizontalAlign , verticalOffset, horizontalOffset)'
9345 ], 9530 ],
9346 9531
9347 attached: function() { 9532 attached: function() {
9348 this.positionTarget = this.positionTarget || this._defaultPositionTarg et;
9349 // Memoize this to avoid expensive calculations & relayouts. 9533 // Memoize this to avoid expensive calculations & relayouts.
9350 this._isRTL = window.getComputedStyle(this).direction == 'rtl'; 9534 this._isRTL = window.getComputedStyle(this).direction == 'rtl';
9535 this.positionTarget = this.positionTarget || this._defaultPositionTarg et;
9351 }, 9536 },
9352 9537
9353 /** 9538 /**
9354 * The element that is contained by the dropdown, if any. 9539 * The element that is contained by the dropdown, if any.
9355 */ 9540 */
9356 get containedElement() { 9541 get containedElement() {
9357 return Polymer.dom(this.$.content).getDistributedNodes()[0]; 9542 return Polymer.dom(this.$.content).getDistributedNodes()[0];
9358 }, 9543 },
9359 9544
9360 /** 9545 /**
(...skipping 27 matching lines...) Expand all
9388 return this.horizontalAlign === 'right' ? 'left' : 'right'; 9573 return this.horizontalAlign === 'right' ? 'left' : 'right';
9389 } else { 9574 } else {
9390 return this.horizontalAlign; 9575 return this.horizontalAlign;
9391 } 9576 }
9392 }, 9577 },
9393 9578
9394 /** 9579 /**
9395 * The horizontal offset value used to position the dropdown. 9580 * The horizontal offset value used to position the dropdown.
9396 * @param {ClientRect} dropdownRect 9581 * @param {ClientRect} dropdownRect
9397 * @param {ClientRect} positionRect 9582 * @param {ClientRect} positionRect
9398 * @param {boolean=false} fromRight 9583 * @param {boolean=} fromRight
9399 * @return {number} pixels 9584 * @return {number} pixels
9400 * @private 9585 * @private
9401 */ 9586 */
9402 _horizontalAlignTargetValue: function(dropdownRect, positionRect, fromRi ght) { 9587 _horizontalAlignTargetValue: function(dropdownRect, positionRect, fromRi ght) {
9403 var target; 9588 var target;
9404 if (fromRight) { 9589 if (fromRight) {
9405 target = document.documentElement.clientWidth - positionRect.right - (this._fitWidth - dropdownRect.right); 9590 target = document.documentElement.clientWidth - positionRect.right - (this._fitWidth - dropdownRect.right);
9406 } else { 9591 } else {
9407 target = positionRect.left - dropdownRect.left; 9592 target = positionRect.left - dropdownRect.left;
9408 } 9593 }
9409 target += this.horizontalOffset; 9594 target += this.horizontalOffset;
9410 9595
9411 return Math.max(target, 0); 9596 return Math.max(target, 0);
9412 }, 9597 },
9413 9598
9414 /** 9599 /**
9415 * The vertical offset value used to position the dropdown. 9600 * The vertical offset value used to position the dropdown.
9416 * @param {ClientRect} dropdownRect 9601 * @param {ClientRect} dropdownRect
9417 * @param {ClientRect} positionRect 9602 * @param {ClientRect} positionRect
9418 * @param {boolean=false} fromBottom 9603 * @param {boolean=} fromBottom
9419 * @return {number} pixels 9604 * @return {number} pixels
9420 * @private 9605 * @private
9421 */ 9606 */
9422 _verticalAlignTargetValue: function(dropdownRect, positionRect, fromBott om) { 9607 _verticalAlignTargetValue: function(dropdownRect, positionRect, fromBott om) {
9423 var target; 9608 var target;
9424 if (fromBottom) { 9609 if (fromBottom) {
9425 target = document.documentElement.clientHeight - positionRect.bottom - (this._fitHeight - dropdownRect.bottom); 9610 target = document.documentElement.clientHeight - positionRect.bottom - (this._fitHeight - dropdownRect.bottom);
9426 } else { 9611 } else {
9427 target = positionRect.top - dropdownRect.top; 9612 target = positionRect.top - dropdownRect.top;
9428 } 9613 }
9429 target += this.verticalOffset; 9614 target += this.verticalOffset;
9430 9615
9431 return Math.max(target, 0); 9616 return Math.max(target, 0);
9432 }, 9617 },
9433 9618
9434 /** 9619 /**
9435 * Called when the value of `opened` changes. 9620 * Called when the value of `opened` changes.
9436 * 9621 * Overridden from `IronOverlayBehavior`
9437 * @param {boolean} opened True if the dropdown is opened.
9438 */ 9622 */
9439 _openedChanged: function(opened) { 9623 _openedChanged: function() {
9440 if (opened && this.disabled) { 9624 if (this.opened && this.disabled) {
9441 this.cancel(); 9625 this.cancel();
9442 } else { 9626 } else {
9443 this.cancelAnimation(); 9627 this.cancelAnimation();
9444 this.sizingTarget = this.containedElement || this.sizingTarget; 9628 this.sizingTarget = this.containedElement || this.sizingTarget;
9445 this._updateAnimationConfig(); 9629 this._updateAnimationConfig();
9630 if (this.opened && !this.allowOutsideScroll) {
9631 Polymer.IronDropdownScrollManager.pushScrollLock(this);
9632 } else {
9633 Polymer.IronDropdownScrollManager.removeScrollLock(this);
9634 }
9446 Polymer.IronOverlayBehaviorImpl._openedChanged.apply(this, arguments ); 9635 Polymer.IronOverlayBehaviorImpl._openedChanged.apply(this, arguments );
9447 } 9636 }
9448 }, 9637 },
9449 9638
9450 /** 9639 /**
9451 * Overridden from `IronOverlayBehavior`. 9640 * Overridden from `IronOverlayBehavior`.
9452 */ 9641 */
9453 _renderOpened: function() { 9642 _renderOpened: function() {
9454 if (!this.allowOutsideScroll) {
9455 Polymer.IronDropdownScrollManager.pushScrollLock(this);
9456 }
9457
9458 if (!this.noAnimations && this.animationConfig && this.animationConfig .open) { 9643 if (!this.noAnimations && this.animationConfig && this.animationConfig .open) {
9459 if (this.withBackdrop) { 9644 if (this.withBackdrop) {
9460 this.backdropElement.open(); 9645 this.backdropElement.open();
9461 } 9646 }
9462 this.$.contentWrapper.classList.add('animating'); 9647 this.$.contentWrapper.classList.add('animating');
9463 this.playAnimation('open'); 9648 this.playAnimation('open');
9464 } else { 9649 } else {
9465 Polymer.IronOverlayBehaviorImpl._renderOpened.apply(this, arguments) ; 9650 Polymer.IronOverlayBehaviorImpl._renderOpened.apply(this, arguments) ;
9466 } 9651 }
9467 }, 9652 },
9468 9653
9469 /** 9654 /**
9470 * Overridden from `IronOverlayBehavior`. 9655 * Overridden from `IronOverlayBehavior`.
9471 */ 9656 */
9472 _renderClosed: function() { 9657 _renderClosed: function() {
9473 Polymer.IronDropdownScrollManager.removeScrollLock(this);
9474 if (!this.noAnimations && this.animationConfig && this.animationConfig .close) { 9658 if (!this.noAnimations && this.animationConfig && this.animationConfig .close) {
9475 if (this.withBackdrop) { 9659 if (this.withBackdrop) {
9476 this.backdropElement.close(); 9660 this.backdropElement.close();
9477 } 9661 }
9478 this.$.contentWrapper.classList.add('animating'); 9662 this.$.contentWrapper.classList.add('animating');
9479 this.playAnimation('close'); 9663 this.playAnimation('close');
9480 } else { 9664 } else {
9481 Polymer.IronOverlayBehaviorImpl._renderClosed.apply(this, arguments) ; 9665 Polymer.IronOverlayBehaviorImpl._renderClosed.apply(this, arguments) ;
9482 } 9666 }
9483 }, 9667 },
(...skipping 1732 matching lines...) Expand 10 before | Expand all | Expand 10 after
11216 // found in the LICENSE file. 11400 // found in the LICENSE file.
11217 11401
11218 // <include src="../../../../ui/webui/resources/js/i18n_template_no_process.js"> 11402 // <include src="../../../../ui/webui/resources/js/i18n_template_no_process.js">
11219 11403
11220 i18nTemplate.process(document, loadTimeData); 11404 i18nTemplate.process(document, loadTimeData);
11221 // Copyright 2015 The Chromium Authors. All rights reserved. 11405 // Copyright 2015 The Chromium Authors. All rights reserved.
11222 // Use of this source code is governed by a BSD-style license that can be 11406 // Use of this source code is governed by a BSD-style license that can be
11223 // found in the LICENSE file. 11407 // found in the LICENSE file.
11224 11408
11225 window.addEventListener('load', downloads.Manager.onLoad); 11409 window.addEventListener('load', downloads.Manager.onLoad);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698