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 29 matching lines...) Expand all Loading... |
166 if (item && !item.isSeparator() && !item.hidden && !item.disabled) | 181 if (item && !item.isSeparator() && !item.hidden && !item.disabled) |
167 break; | 182 break; |
168 } | 183 } |
169 if (item && !item.disabled) | 184 if (item && !item.disabled) |
170 self.selectedIndex = i; | 185 self.selectedIndex = i; |
171 } | 186 } |
172 | 187 |
173 switch (e.keyIdentifier) { | 188 switch (e.keyIdentifier) { |
174 case 'Down': | 189 case 'Down': |
175 selectNextAvailable(1); | 190 selectNextAvailable(1); |
| 191 this.focusSelectedItem(); |
176 return true; | 192 return true; |
177 case 'Up': | 193 case 'Up': |
178 selectNextAvailable(-1); | 194 selectNextAvailable(-1); |
| 195 this.focusSelectedItem(); |
179 return true; | 196 return true; |
180 case 'Enter': | 197 case 'Enter': |
181 case 'U+0020': // Space | 198 case 'U+0020': // Space |
182 if (item) { | 199 if (item) { |
183 if (cr.dispatchSimpleEvent(item, 'activate', true, true)) { | 200 var activationEvent = cr.doc.createEvent('Event'); |
| 201 activationEvent.initEvent('activate', true, true); |
| 202 activationEvent.originalEvent = e; |
| 203 if (item.dispatchEvent(activationEvent)) { |
184 if (item.command) | 204 if (item.command) |
185 item.command.execute(); | 205 item.command.execute(); |
186 } | 206 } |
187 } | 207 } |
188 return true; | 208 return true; |
189 } | 209 } |
190 | 210 |
191 return false; | 211 return false; |
192 }, | 212 }, |
193 | 213 |
194 /** | 214 /** |
195 * Updates menu items command according to context. | 215 * Updates menu items command according to context. |
196 * @param {Node=} node Node for which to actuate commands state. | 216 * @param {Node=} node Node for which to actuate commands state. |
197 */ | 217 */ |
198 updateCommands: function(node) { | 218 updateCommands: function(node) { |
199 var children = this.children; | 219 var children = this.children; |
200 | 220 |
201 for (var i = 0, child; child = children[i]; i++) | 221 for (var i = 0, child; child = children[i]; i++) |
202 child.updateCommand(node); | 222 child.updateCommand(node); |
203 } | 223 } |
204 }; | 224 }; |
205 | 225 |
206 function selectedIndexChanged(selectedIndex, oldSelectedIndex) { | 226 function selectedIndexChanged(selectedIndex, oldSelectedIndex) { |
207 var oldSelectedItem = this.children[oldSelectedIndex]; | 227 var oldSelectedItem = this.children[oldSelectedIndex]; |
208 if (oldSelectedItem) | 228 if (oldSelectedItem) { |
209 oldSelectedItem.selected = false; | 229 oldSelectedItem.selected = false; |
| 230 oldSelectedItem.blur(); |
| 231 } |
210 var item = this.selectedItem; | 232 var item = this.selectedItem; |
211 if (item) | 233 if (item) |
212 item.selected = true; | 234 item.selected = true; |
213 } | 235 } |
214 | 236 |
215 /** | 237 /** |
216 * The selected menu item. | 238 * The selected menu item. |
217 * @type {number} | 239 * @type {number} |
218 */ | 240 */ |
219 cr.defineProperty(Menu, 'selectedIndex', cr.PropertyKind.JS, | 241 cr.defineProperty(Menu, 'selectedIndex', cr.PropertyKind.JS, |
220 selectedIndexChanged); | 242 selectedIndexChanged); |
221 | 243 |
222 // Export | 244 // Export |
223 return { | 245 return { |
224 Menu: Menu | 246 Menu: Menu |
225 }; | 247 }; |
226 }); | 248 }); |
OLD | NEW |