OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 Polymer({ | 5 Polymer({ |
6 is: 'cr-action-menu', | 6 is: 'cr-action-menu', |
7 extends: 'dialog', | 7 extends: 'dialog', |
8 | 8 |
9 /** | 9 /** |
10 * List of all options in this action menu. | 10 * List of all options in this action menu. |
(...skipping 23 matching lines...) Expand all Loading... |
34 'keydown': 'onKeyDown_', | 34 'keydown': 'onKeyDown_', |
35 'tap': 'onTap_', | 35 'tap': 'onTap_', |
36 }, | 36 }, |
37 | 37 |
38 /** override */ | 38 /** override */ |
39 attached: function() { | 39 attached: function() { |
40 this.options_ = this.querySelectorAll('.dropdown-item'); | 40 this.options_ = this.querySelectorAll('.dropdown-item'); |
41 }, | 41 }, |
42 | 42 |
43 /** override */ | 43 /** override */ |
44 detached: function() { | 44 detached: function() { this.removeResizeListener_(); }, |
45 this.removeResizeListener_(); | |
46 }, | |
47 | 45 |
48 /** @private */ | 46 /** @private */ |
49 removeResizeListener_: function() { | 47 removeResizeListener_: function() { |
50 window.removeEventListener('resize', this.onWindowResize_); | 48 window.removeEventListener('resize', this.onWindowResize_); |
51 }, | 49 }, |
52 | 50 |
53 /** | 51 /** |
54 * @param {!Event} e | 52 * @param {!Event} e |
55 * @private | 53 * @private |
56 */ | 54 */ |
(...skipping 11 matching lines...) Expand all Loading... |
68 onKeyDown_: function(e) { | 66 onKeyDown_: function(e) { |
69 if (e.key == 'Tab' || e.key == 'Escape') { | 67 if (e.key == 'Tab' || e.key == 'Escape') { |
70 this.close(); | 68 this.close(); |
71 e.preventDefault(); | 69 e.preventDefault(); |
72 return; | 70 return; |
73 } | 71 } |
74 | 72 |
75 if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp') | 73 if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp') |
76 return; | 74 return; |
77 | 75 |
78 var nextOption = this.getNextOption_(e.key == 'ArrowDown' ? 1 : - 1); | 76 var nextOption = this.getNextOption_(e.key == 'ArrowDown' ? 1 : -1); |
79 if (nextOption) | 77 if (nextOption) |
80 nextOption.focus(); | 78 nextOption.focus(); |
81 | 79 |
82 e.preventDefault(); | 80 e.preventDefault(); |
83 }, | 81 }, |
84 | 82 |
85 /** | 83 /** |
86 * @param {number} step -1 for getting previous option (up), 1 for getting | 84 * @param {number} step -1 for getting previous option (up), 1 for getting |
87 * next option (down). | 85 * next option (down). |
88 * @return {?Element} The next focusable option, taking into account | 86 * @return {?Element} The next focusable option, taking into account |
89 * disabled/hidden attributes, or null if no focusable option exists. | 87 * disabled/hidden attributes, or null if no focusable option exists. |
90 * @private | 88 * @private |
91 */ | 89 */ |
92 getNextOption_: function(step) { | 90 getNextOption_: function(step) { |
93 // Using a counter to ensure no infinite loop occurs if all elements are | 91 // Using a counter to ensure no infinite loop occurs if all elements are |
94 // hidden/disabled. | 92 // hidden/disabled. |
95 var counter = 0; | 93 var counter = 0; |
96 var nextOption = null; | 94 var nextOption = null; |
97 var numOptions = this.options_.length; | 95 var numOptions = this.options_.length; |
98 var focusedIndex = Array.prototype.indexOf.call( | 96 var focusedIndex = |
99 this.options_, this.root.activeElement); | 97 Array.prototype.indexOf.call(this.options_, this.root.activeElement); |
100 | 98 |
101 do { | 99 do { |
102 focusedIndex = (numOptions + focusedIndex + step) % numOptions; | 100 focusedIndex = (numOptions + focusedIndex + step) % numOptions; |
103 nextOption = this.options_[focusedIndex]; | 101 nextOption = this.options_[focusedIndex]; |
104 if (nextOption.disabled || nextOption.hidden) | 102 if (nextOption.disabled || nextOption.hidden) |
105 nextOption = null; | 103 nextOption = null; |
106 counter++; | 104 counter++; |
107 } while (!nextOption && counter < numOptions); | 105 } while (!nextOption && counter < numOptions); |
108 | 106 |
109 return nextOption; | 107 return nextOption; |
(...skipping 27 matching lines...) Expand all Loading... |
137 var right = window.innerWidth - rect.left - this.offsetWidth; | 135 var right = window.innerWidth - rect.left - this.offsetWidth; |
138 this.style.right = right + 'px'; | 136 this.style.right = right + 'px'; |
139 } else { | 137 } else { |
140 var left = rect.right - this.offsetWidth; | 138 var left = rect.right - this.offsetWidth; |
141 this.style.left = left + 'px'; | 139 this.style.left = left + 'px'; |
142 } | 140 } |
143 | 141 |
144 // Attempt to show the menu starting from the top of the rectangle and | 142 // Attempt to show the menu starting from the top of the rectangle and |
145 // extending downwards. If that does not fit within the window, fallback to | 143 // extending downwards. If that does not fit within the window, fallback to |
146 // starting from the bottom and extending upwards. | 144 // starting from the bottom and extending upwards. |
147 var top = rect.top + this.offsetHeight <= window.innerHeight ? | 145 var top = rect.top + this.offsetHeight <= window.innerHeight ? rect.top : |
148 rect.top : | 146 rect.bottom - |
149 rect.bottom - this.offsetHeight - Math.max( | 147 this.offsetHeight - Math.max(rect.bottom - window.innerHeight, 0); |
150 rect.bottom - window.innerHeight, 0); | |
151 | 148 |
152 this.style.top = top + 'px'; | 149 this.style.top = top + 'px'; |
153 }, | 150 }, |
154 }); | 151 }); |
OLD | NEW |