OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 cr.define('cr.ui', function() { | 5 cr.define('cr.ui', function() { |
6 /** @const */ | 6 /** @const */ |
7 var Menu = cr.ui.Menu; | 7 var Menu = cr.ui.Menu; |
8 /** @const */ | 8 /** @const */ |
9 var positionPopupAroundElement = cr.ui.positionPopupAroundElement; | 9 var positionPopupAroundElement = cr.ui.positionPopupAroundElement; |
10 | 10 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
76 if (e.currentTarget == this.ownerDocument) { | 76 if (e.currentTarget == this.ownerDocument) { |
77 if (!this.contains(e.target) && !this.menu.contains(e.target)) | 77 if (!this.contains(e.target) && !this.menu.contains(e.target)) |
78 this.hideMenu(); | 78 this.hideMenu(); |
79 else | 79 else |
80 e.preventDefault(); | 80 e.preventDefault(); |
81 } else { | 81 } else { |
82 if (this.isMenuShown()) { | 82 if (this.isMenuShown()) { |
83 this.hideMenu(); | 83 this.hideMenu(); |
84 } else if (e.button == 0) { // Only show the menu when using left | 84 } else if (e.button == 0) { // Only show the menu when using left |
85 // mouse button. | 85 // mouse button. |
86 this.showMenu(); | 86 this.showMenu(false); |
87 // Prevent the button from stealing focus on mousedown. | 87 // Prevent the button from stealing focus on mousedown. |
88 e.preventDefault(); | 88 e.preventDefault(); |
89 } | 89 } |
90 } | 90 } |
91 break; | 91 break; |
92 case 'keydown': | 92 case 'keydown': |
93 this.handleKeyDown(e); | 93 this.handleKeyDown(e); |
94 // If the menu is visible we let it handle all the keyboard events. | 94 // If the menu is visible we let it handle all the keyboard events. |
95 if (this.isMenuShown() && e.currentTarget == this.ownerDocument) { | 95 if (this.isMenuShown() && e.currentTarget == this.ownerDocument) { |
96 this.menu.handleKeyDown(e); | 96 if (this.menu.handleKeyDown(e)) { |
97 e.preventDefault(); | 97 e.preventDefault(); |
98 e.stopPropagation(); | 98 e.stopPropagation(); |
99 } | |
99 } | 100 } |
100 break; | 101 break; |
101 | 102 |
103 case 'focus': | |
Dan Beam
2012/11/12 22:55:03
is there a functional difference between "focus on
aboxhall
2012/11/13 00:49:52
Yep - at the time of blur, the new document.active
| |
104 if (!this.contains(e.target) && !this.menu.contains(e.target)) | |
105 this.hideMenu(); | |
106 break; | |
107 | |
102 case 'activate': | 108 case 'activate': |
103 case 'blur': | |
104 case 'resize': | 109 case 'resize': |
105 this.hideMenu(); | 110 this.hideMenu(); |
106 break; | 111 break; |
107 } | 112 } |
108 }, | 113 }, |
109 | 114 |
110 /** | 115 /** |
111 * Shows the menu. | 116 * Shows the menu. |
117 * @param {boolean} shouldSetFocus Whether to set focus on the | |
Dan Beam
2012/11/12 22:55:03
nit: is this boolean optional to pass? i.e. is the
aboxhall
2012/11/13 00:49:52
I agree, and I'm pretty sure I changed all call si
| |
118 * selected menu item. | |
112 */ | 119 */ |
113 showMenu: function() { | 120 showMenu: function(shouldSetFocus) { |
114 this.hideMenu(); | 121 this.hideMenu(); |
115 | 122 |
116 var event = document.createEvent('UIEvents'); | 123 var event = document.createEvent('UIEvents'); |
117 event.initUIEvent('menushow', true, true, window, null); | 124 event.initUIEvent('menushow', true, true, window, null); |
118 | 125 |
119 if (this.dispatchEvent(event)) { | 126 if (this.dispatchEvent(event)) { |
120 this.menu.hidden = false; | 127 this.menu.hidden = false; |
121 | 128 |
122 this.setAttribute('menu-shown', ''); | 129 this.setAttribute('menu-shown', ''); |
130 if (shouldSetFocus) | |
131 this.menu.focusSelectedItem(); | |
123 | 132 |
124 // when the menu is shown we steal all keyboard events. | 133 // when the menu is shown we steal all keyboard events. |
125 var doc = this.ownerDocument; | 134 var doc = this.ownerDocument; |
126 var win = doc.defaultView; | 135 var win = doc.defaultView; |
127 this.showingEvents_.add(doc, 'keydown', this, true); | 136 this.showingEvents_.add(doc, 'keydown', this, true); |
128 this.showingEvents_.add(doc, 'mousedown', this, true); | 137 this.showingEvents_.add(doc, 'mousedown', this, true); |
129 this.showingEvents_.add(doc, 'blur', this, true); | 138 this.showingEvents_.add(doc, 'focus', this, true); |
130 this.showingEvents_.add(win, 'resize', this); | 139 this.showingEvents_.add(win, 'resize', this); |
131 this.showingEvents_.add(this.menu, 'activate', this); | 140 this.showingEvents_.add(this.menu, 'activate', this); |
132 this.positionMenu_(); | 141 this.positionMenu_(); |
133 } | 142 } |
134 }, | 143 }, |
135 | 144 |
136 /** | 145 /** |
137 * Hides the menu. If your menu can go out of scope, make sure to call this | 146 * Hides the menu. If your menu can go out of scope, make sure to call this |
138 * first. | 147 * first. |
139 */ | 148 */ |
140 hideMenu: function() { | 149 hideMenu: function() { |
141 if (!this.isMenuShown()) | 150 if (!this.isMenuShown()) |
142 return; | 151 return; |
143 | 152 |
144 this.removeAttribute('menu-shown'); | 153 this.removeAttribute('menu-shown'); |
145 this.menu.hidden = true; | 154 this.menu.hidden = true; |
146 | 155 |
147 this.showingEvents_.removeAll(); | 156 this.showingEvents_.removeAll(); |
148 this.menu.selectedIndex = -1; | 157 this.focus(); |
149 }, | 158 }, |
150 | 159 |
151 /** | 160 /** |
152 * Whether the menu is shown. | 161 * Whether the menu is shown. |
153 */ | 162 */ |
154 isMenuShown: function() { | 163 isMenuShown: function() { |
155 return this.hasAttribute('menu-shown'); | 164 return this.hasAttribute('menu-shown'); |
156 }, | 165 }, |
157 | 166 |
158 /** | 167 /** |
159 * Positions the menu below the menu button. At this point we do not use any | 168 * Positions the menu below the menu button. At this point we do not use any |
160 * advanced positioning logic to ensure the menu fits in the viewport. | 169 * advanced positioning logic to ensure the menu fits in the viewport. |
161 * @private | 170 * @private |
162 */ | 171 */ |
163 positionMenu_: function() { | 172 positionMenu_: function() { |
164 positionPopupAroundElement(this, this.menu, this.anchorType, | 173 positionPopupAroundElement(this, this.menu, this.anchorType, |
165 this.invertLeftRight); | 174 this.invertLeftRight); |
166 }, | 175 }, |
167 | 176 |
168 /** | 177 /** |
169 * Handles the keydown event for the menu button. | 178 * Handles the keydown event for the menu button. |
170 */ | 179 */ |
171 handleKeyDown: function(e) { | 180 handleKeyDown: function(e) { |
172 switch (e.keyIdentifier) { | 181 switch (e.keyIdentifier) { |
173 case 'Down': | 182 case 'Down': |
174 case 'Up': | 183 case 'Up': |
175 case 'Enter': | 184 case 'Enter': |
176 case 'U+0020': // Space | 185 case 'U+0020': // Space |
177 if (!this.isMenuShown()) | 186 if (!this.isMenuShown()) |
178 this.showMenu(); | 187 this.showMenu(true); |
179 e.preventDefault(); | 188 e.preventDefault(); |
180 break; | 189 break; |
181 case 'Esc': | 190 case 'Esc': |
182 case 'U+001B': // Maybe this is remote desktop playing a prank? | 191 case 'U+001B': // Maybe this is remote desktop playing a prank? |
192 case 'U+0009': // Tab | |
183 this.hideMenu(); | 193 this.hideMenu(); |
184 break; | 194 break; |
185 } | 195 } |
186 } | 196 } |
187 }; | 197 }; |
188 | 198 |
189 /** | 199 /** |
190 * Helper for styling a menu button with a drop-down arrow indicator. | 200 * Helper for styling a menu button with a drop-down arrow indicator. |
191 * Creates a new 2D canvas context and draws a downward-facing arrow into it. | 201 * Creates a new 2D canvas context and draws a downward-facing arrow into it. |
192 * @param {string} canvasName The name of the canvas. The canvas can be | 202 * @param {string} canvasName The name of the canvas. The canvas can be |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
230 'drop-down-arrow-hover', ARROW_WIDTH, ARROW_HEIGHT, hoverColor); | 240 'drop-down-arrow-hover', ARROW_WIDTH, ARROW_HEIGHT, hoverColor); |
231 createDropDownArrowCanvas( | 241 createDropDownArrowCanvas( |
232 'drop-down-arrow-active', ARROW_WIDTH, ARROW_HEIGHT, activeColor); | 242 'drop-down-arrow-active', ARROW_WIDTH, ARROW_HEIGHT, activeColor); |
233 }; | 243 }; |
234 | 244 |
235 // Export | 245 // Export |
236 return { | 246 return { |
237 MenuButton: MenuButton | 247 MenuButton: MenuButton |
238 }; | 248 }; |
239 }); | 249 }); |
OLD | NEW |