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 | 6 |
7 /** @const */ var MenuItem = cr.ui.MenuItem; | 7 /** @const */ var MenuItem = cr.ui.MenuItem; |
8 | 8 |
9 /** | 9 /** |
10 * Creates a new menu element. Menu dispatches all commands on the element it | 10 * Creates a new menu element. Menu dispatches all commands on the element it |
(...skipping 16 matching lines...) Expand all Loading... |
27 contextElement: null, | 27 contextElement: null, |
28 | 28 |
29 /** | 29 /** |
30 * Initializes the menu element. | 30 * Initializes the menu element. |
31 */ | 31 */ |
32 decorate: function() { | 32 decorate: function() { |
33 this.addEventListener('mouseover', this.handleMouseOver_); | 33 this.addEventListener('mouseover', this.handleMouseOver_); |
34 this.addEventListener('mouseout', this.handleMouseOut_); | 34 this.addEventListener('mouseout', this.handleMouseOut_); |
35 | 35 |
36 this.classList.add('decorated'); | 36 this.classList.add('decorated'); |
| 37 this.setAttribute('role', 'menu'); |
37 this.hidden = true; // Hide the menu by default. | 38 this.hidden = true; // Hide the menu by default. |
38 | 39 |
39 // Decorate the children as menu items. | 40 // Decorate the children as menu items. |
40 var children = this.children; | 41 var children = this.children; |
41 for (var i = 0, child; child = children[i]; i++) { | 42 for (var i = 0, child; child = children[i]; i++) { |
42 cr.ui.decorate(child, MenuItem); | 43 cr.ui.decorate(child, MenuItem); |
43 } | 44 } |
44 }, | 45 }, |
45 | 46 |
46 /** | 47 /** |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 */ | 118 */ |
118 get selectedItem() { | 119 get selectedItem() { |
119 return this.children[this.selectedIndex]; | 120 return this.children[this.selectedIndex]; |
120 }, | 121 }, |
121 set selectedItem(item) { | 122 set selectedItem(item) { |
122 var index = Array.prototype.indexOf.call(this.children, item); | 123 var index = Array.prototype.indexOf.call(this.children, item); |
123 this.selectedIndex = index; | 124 this.selectedIndex = index; |
124 }, | 125 }, |
125 | 126 |
126 /** | 127 /** |
| 128 * Focuses the selected item. If selectedIndex is invalid, set it to 0 |
| 129 * first. |
| 130 */ |
| 131 focusSelectedItem: function() { |
| 132 if (this.selectedIndex < 0 || |
| 133 this.selectedIndex > this.children.length) { |
| 134 this.selectedIndex = 0; |
| 135 } |
| 136 |
| 137 if (this.selectedItem) |
| 138 this.selectedItem.focus(); |
| 139 }, |
| 140 |
| 141 /** |
127 * Menu length | 142 * Menu length |
128 */ | 143 */ |
129 get length() { | 144 get length() { |
130 return this.children.length; | 145 return this.children.length; |
131 }, | 146 }, |
132 | 147 |
133 /** | 148 /** |
134 * This is the function that handles keyboard navigation. This is usually | 149 * This is the function that handles keyboard navigation. This is usually |
135 * called by the element responsible for managing the menu. | 150 * called by the element responsible for managing the menu. |
136 * @param {Event} e The keydown event object. | 151 * @param {Event} e The keydown event object. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 switch (e.keyIdentifier) { | 188 switch (e.keyIdentifier) { |
174 case 'Down': | 189 case 'Down': |
175 selectNextAvailable(1); | 190 selectNextAvailable(1); |
176 return true; | 191 return true; |
177 case 'Up': | 192 case 'Up': |
178 selectNextAvailable(-1); | 193 selectNextAvailable(-1); |
179 return true; | 194 return true; |
180 case 'Enter': | 195 case 'Enter': |
181 case 'U+0020': // Space | 196 case 'U+0020': // Space |
182 if (item) { | 197 if (item) { |
183 if (cr.dispatchSimpleEvent(item, 'activate', true, true)) { | 198 var activationEvent = cr.doc.createEvent('Event'); |
| 199 activationEvent.initEvent('activate', true, true); |
| 200 activationEvent.originalEvent = e; |
| 201 if (item.dispatchEvent(activationEvent)) { |
184 if (item.command) | 202 if (item.command) |
185 item.command.execute(); | 203 item.command.execute(); |
186 } | 204 } |
187 } | 205 } |
188 return true; | 206 return true; |
189 } | 207 } |
190 | 208 |
191 return false; | 209 return false; |
192 }, | 210 }, |
193 | 211 |
194 /** | 212 /** |
195 * Updates menu items command according to context. | 213 * Updates menu items command according to context. |
196 * @param {Node=} node Node for which to actuate commands state. | 214 * @param {Node=} node Node for which to actuate commands state. |
197 */ | 215 */ |
198 updateCommands: function(node) { | 216 updateCommands: function(node) { |
199 var children = this.children; | 217 var children = this.children; |
200 | 218 |
201 for (var i = 0, child; child = children[i]; i++) | 219 for (var i = 0, child; child = children[i]; i++) |
202 child.updateCommand(node); | 220 child.updateCommand(node); |
203 } | 221 } |
204 }; | 222 }; |
205 | 223 |
206 function selectedIndexChanged(selectedIndex, oldSelectedIndex) { | 224 function selectedIndexChanged(selectedIndex, oldSelectedIndex) { |
207 var oldSelectedItem = this.children[oldSelectedIndex]; | 225 var oldSelectedItem = this.children[oldSelectedIndex]; |
208 if (oldSelectedItem) | 226 if (oldSelectedItem) |
209 oldSelectedItem.selected = false; | 227 oldSelectedItem.selected = false; |
210 var item = this.selectedItem; | 228 var item = this.selectedItem; |
211 if (item) | 229 if (item) { |
212 item.selected = true; | 230 item.selected = true; |
| 231 this.focusSelectedItem(); |
| 232 } |
213 } | 233 } |
214 | 234 |
215 /** | 235 /** |
216 * The selected menu item. | 236 * The selected menu item. |
217 * @type {number} | 237 * @type {number} |
218 */ | 238 */ |
219 cr.defineProperty(Menu, 'selectedIndex', cr.PropertyKind.JS, | 239 cr.defineProperty(Menu, 'selectedIndex', cr.PropertyKind.JS, |
220 selectedIndexChanged); | 240 selectedIndexChanged); |
221 | 241 |
222 // Export | 242 // Export |
223 return { | 243 return { |
224 Menu: Menu | 244 Menu: Menu |
225 }; | 245 }; |
226 }); | 246 }); |
OLD | NEW |