OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 Network drop-down implementation. | 6 * @fileoverview Network drop-down implementation. |
7 */ | 7 */ |
8 | 8 |
9 cr.define('cr.ui', function() { | 9 cr.define('cr.ui', function() { |
10 /** | 10 /** |
11 * Creates a new container for the drop down menu items. | 11 * Creates a new container for the drop down menu items. |
12 * @constructor | 12 * @constructor |
13 * @extends {HTMLDivElement} | 13 * @extends {HTMLDivElement} |
14 */ | 14 */ |
15 var DropDownContainer = cr.ui.define('div'); | 15 var DropDownContainer = cr.ui.define('div'); |
16 | 16 |
17 DropDownContainer.prototype = { | 17 DropDownContainer.prototype = { |
18 __proto__: HTMLDivElement.prototype, | 18 __proto__: HTMLDivElement.prototype, |
19 | 19 |
20 /** @inheritDoc */ | 20 /** @inheritDoc */ |
21 decorate: function() { | 21 decorate: function() { |
22 this.classList.add('dropdown-container'); | 22 this.classList.add('dropdown-container'); |
23 // Selected item in the menu list. | 23 // Selected item in the menu list. |
24 this.selectedItem = null; | 24 this.selectedItem = null; |
25 // First item which could be selected. | 25 // First item which could be selected. |
26 this.firstItem = null; | 26 this.firstItem = null; |
| 27 this.setAttribute('role', 'menu'); |
27 // Whether scroll has just happened. | 28 // Whether scroll has just happened. |
28 this.scrollJustHappened = false; | 29 this.scrollJustHappened = false; |
29 }, | 30 }, |
30 | 31 |
31 /** | 32 /** |
32 * Gets scroll action to be done for the item. | 33 * Gets scroll action to be done for the item. |
33 * @param {!Object} item Menu item. | 34 * @param {!Object} item Menu item. |
34 * @return {integer} -1 for scroll up; 0 for no action; 1 for scroll down. | 35 * @return {integer} -1 for scroll up; 0 for no action; 1 for scroll down. |
35 */ | 36 */ |
36 scrollAction: function(item) { | 37 scrollAction: function(item) { |
(...skipping 13 matching lines...) Expand all Loading... |
50 */ | 51 */ |
51 selectItem: function(selectedItem, mouseOver) { | 52 selectItem: function(selectedItem, mouseOver) { |
52 if (mouseOver && this.scrollJustHappened) { | 53 if (mouseOver && this.scrollJustHappened) { |
53 this.scrollJustHappened = false; | 54 this.scrollJustHappened = false; |
54 return; | 55 return; |
55 } | 56 } |
56 if (this.selectedItem) | 57 if (this.selectedItem) |
57 this.selectedItem.classList.remove('hover'); | 58 this.selectedItem.classList.remove('hover'); |
58 selectedItem.classList.add('hover'); | 59 selectedItem.classList.add('hover'); |
59 this.selectedItem = selectedItem; | 60 this.selectedItem = selectedItem; |
| 61 if (!this.hidden) { |
| 62 this.previousSibling.setAttribute( |
| 63 'aria-activedescendant', selectedItem.id); |
| 64 } |
60 var action = this.scrollAction(selectedItem); | 65 var action = this.scrollAction(selectedItem); |
61 if (action != 0) { | 66 if (action != 0) { |
62 selectedItem.scrollIntoView(action < 0); | 67 selectedItem.scrollIntoView(action < 0); |
63 this.scrollJustHappened = true; | 68 this.scrollJustHappened = true; |
64 } | 69 } |
65 } | 70 } |
66 }; | 71 }; |
67 | 72 |
68 /** | 73 /** |
69 * Creates a new DropDown div. | 74 * Creates a new DropDown div. |
70 * @constructor | 75 * @constructor |
71 * @extends {HTMLDivElement} | 76 * @extends {HTMLDivElement} |
72 */ | 77 */ |
73 var DropDown = cr.ui.define('div'); | 78 var DropDown = cr.ui.define('div'); |
74 | 79 |
75 DropDown.ITEM_DIVIDER_ID = -2; | 80 DropDown.ITEM_DIVIDER_ID = -2; |
76 | 81 |
77 DropDown.prototype = { | 82 DropDown.prototype = { |
78 __proto__: HTMLDivElement.prototype, | 83 __proto__: HTMLDivElement.prototype, |
79 | 84 |
80 /** @inheritDoc */ | 85 /** @inheritDoc */ |
81 decorate: function() { | 86 decorate: function() { |
82 this.appendChild(this.createOverlay_()); | 87 this.appendChild(this.createOverlay_()); |
83 this.appendChild(this.createTitle_()); | 88 this.appendChild(this.title_ = this.createTitle_()); |
84 this.appendChild(new DropDownContainer()); | 89 this.appendChild(new DropDownContainer()); |
85 | 90 |
86 this.isShown = false; | 91 this.isShown = false; |
87 this.addEventListener('keydown', this.keyDownHandler_); | 92 this.addEventListener('keydown', this.keyDownHandler_); |
| 93 |
| 94 this.title_.id = this.id + '-dropdown'; |
| 95 this.title_.setAttribute('role', 'button'); |
| 96 this.title_.setAttribute('aria-haspopup', 'true'); |
88 }, | 97 }, |
89 | 98 |
90 /** | 99 /** |
91 * Returns true if dropdown menu is shown. | 100 * Returns true if dropdown menu is shown. |
92 * @type {bool} Whether menu element is shown. | 101 * @type {bool} Whether menu element is shown. |
93 */ | 102 */ |
94 get isShown() { | 103 get isShown() { |
95 return !this.container.hidden; | 104 return !this.container.hidden; |
96 }, | 105 }, |
97 | 106 |
98 /** | 107 /** |
99 * Sets dropdown menu visibility. | 108 * Sets dropdown menu visibility. |
100 * @param {bool} show New visibility state for dropdown menu. | 109 * @param {bool} show New visibility state for dropdown menu. |
101 */ | 110 */ |
102 set isShown(show) { | 111 set isShown(show) { |
103 this.firstElementChild.hidden = !show; | 112 this.firstElementChild.hidden = !show; |
104 this.container.hidden = !show; | 113 this.container.hidden = !show; |
105 if (show) | 114 if (show) { |
106 this.container.selectItem(this.container.firstItem, false); | 115 this.container.selectItem(this.container.firstItem, false); |
| 116 this.title_.setAttribute('aria-pressed', 'true'); |
| 117 } else { |
| 118 this.title_.setAttribute('aria-pressed', 'false'); |
| 119 this.title_.removeAttribute('aria-activedescendant'); |
| 120 } |
107 }, | 121 }, |
108 | 122 |
109 /** | 123 /** |
110 * Returns title button. | 124 * Returns title button. |
111 */ | 125 */ |
112 get titleButton() { | 126 get titleButton() { |
113 return this.children[1]; | 127 return this.children[1]; |
114 }, | 128 }, |
115 | 129 |
116 /** | 130 /** |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 if (item.id == DropDown.ITEM_DIVIDER_ID) { | 184 if (item.id == DropDown.ITEM_DIVIDER_ID) { |
171 className = 'dropdown-divider'; | 185 className = 'dropdown-divider'; |
172 itemContentElement = this.ownerDocument.createElement('hr'); | 186 itemContentElement = this.ownerDocument.createElement('hr'); |
173 } else { | 187 } else { |
174 var span = this.ownerDocument.createElement('span'); | 188 var span = this.ownerDocument.createElement('span'); |
175 itemContentElement = span; | 189 itemContentElement = span; |
176 span.textContent = item.label; | 190 span.textContent = item.label; |
177 if ('bold' in item && item.bold) | 191 if ('bold' in item && item.bold) |
178 span.classList.add('bold'); | 192 span.classList.add('bold'); |
179 var image = this.ownerDocument.createElement('img'); | 193 var image = this.ownerDocument.createElement('img'); |
| 194 image.alt = ''; |
180 if (item.icon) | 195 if (item.icon) |
181 image.src = item.icon; | 196 image.src = item.icon; |
182 } | 197 } |
183 | 198 |
184 var itemElement = this.ownerDocument.createElement('div'); | 199 var itemElement = this.ownerDocument.createElement('div'); |
185 itemElement.classList.add(className); | 200 itemElement.classList.add(className); |
186 itemElement.appendChild(itemContentElement); | 201 itemElement.appendChild(itemContentElement); |
187 itemElement.iid = item.id; | 202 itemElement.iid = item.id; |
188 itemElement.controller = this; | 203 itemElement.controller = this; |
189 var enabled = 'enabled' in item && item.enabled; | 204 var enabled = 'enabled' in item && item.enabled; |
190 if (!enabled) | 205 if (!enabled) |
191 itemElement.classList.add('disabled-item'); | 206 itemElement.classList.add('disabled-item'); |
192 | 207 |
193 if (item.id > 0) { | 208 if (item.id > 0) { |
194 var wrapperDiv = this.ownerDocument.createElement('div'); | 209 var wrapperDiv = this.ownerDocument.createElement('div'); |
| 210 wrapperDiv.setAttribute('role', 'menuitem'); |
| 211 wrapperDiv.id = this.id + item.id; |
| 212 if (!enabled) |
| 213 wrapperDiv.setAttribute('aria-disabled', 'true'); |
195 wrapperDiv.classList.add('dropdown-item-container'); | 214 wrapperDiv.classList.add('dropdown-item-container'); |
196 var imageDiv = this.ownerDocument.createElement('div'); | 215 var imageDiv = this.ownerDocument.createElement('div'); |
197 imageDiv.classList.add('dropdown-image'); | 216 imageDiv.classList.add('dropdown-image'); |
198 imageDiv.appendChild(image); | 217 imageDiv.appendChild(image); |
199 wrapperDiv.appendChild(imageDiv); | 218 wrapperDiv.appendChild(imageDiv); |
200 wrapperDiv.appendChild(itemElement); | 219 wrapperDiv.appendChild(itemElement); |
201 wrapperDiv.addEventListener('click', function f(e) { | 220 wrapperDiv.addEventListener('click', function f(e) { |
202 var item = this.lastElementChild; | 221 var item = this.lastElementChild; |
203 if (item.iid < -1 || item.classList.contains('disabled-item')) | 222 if (item.iid < -1 || item.classList.contains('disabled-item')) |
204 return; | 223 return; |
(...skipping 28 matching lines...) Expand all Loading... |
233 return overlay; | 252 return overlay; |
234 }, | 253 }, |
235 | 254 |
236 /** | 255 /** |
237 * Creates dropdown title element. | 256 * Creates dropdown title element. |
238 * @type {HTMLElement} | 257 * @type {HTMLElement} |
239 * @private | 258 * @private |
240 */ | 259 */ |
241 createTitle_: function() { | 260 createTitle_: function() { |
242 var image = this.ownerDocument.createElement('img'); | 261 var image = this.ownerDocument.createElement('img'); |
| 262 image.alt = ''; |
243 var text = this.ownerDocument.createElement('div'); | 263 var text = this.ownerDocument.createElement('div'); |
244 | 264 |
245 var el = this.ownerDocument.createElement('div'); | 265 var el = this.ownerDocument.createElement('div'); |
246 el.appendChild(image); | 266 el.appendChild(image); |
247 el.appendChild(text); | 267 el.appendChild(text); |
248 | 268 |
249 el.tabIndex = 0; | 269 el.tabIndex = 0; |
250 el.classList.add('dropdown-title'); | 270 el.classList.add('dropdown-title'); |
251 el.iid = -1; | 271 el.iid = -1; |
252 el.controller = this; | 272 el.controller = this; |
253 el.inFocus = false; | 273 el.inFocus = false; |
254 el.opening = false; | 274 el.opening = false; |
255 | 275 |
256 el.addEventListener('click', function f(e) { | 276 el.addEventListener('click', function f(e) { |
257 this.controller.isShown = !this.controller.isShown; | 277 this.controller.isShown = !this.controller.isShown; |
258 }); | 278 }); |
259 | 279 |
260 el.addEventListener('focus', function(e) { | 280 el.addEventListener('focus', function(e) { |
261 this.inFocus = true; | 281 this.inFocus = true; |
262 }); | 282 }); |
263 | 283 |
264 el.addEventListener('blur', function(e) { | 284 el.addEventListener('blur', function(e) { |
265 this.inFocus = false; | 285 this.inFocus = false; |
266 }); | 286 }); |
267 | 287 |
268 el.addEventListener('keydown', function f(e) { | 288 el.addEventListener('keydown', function f(e) { |
269 if (this.inFocus && !this.controller.isShown && e.keyCode == 13) { | 289 if (this.inFocus && !this.controller.isShown && |
270 // Enter has been pressed. | 290 (e.keyCode == 13 || e.keyCode == 32)) { |
| 291 // Enter or space has been pressed. |
271 this.opening = true; | 292 this.opening = true; |
272 this.controller.isShown = true; | 293 this.controller.isShown = true; |
273 } | 294 } |
274 }); | 295 }); |
275 return el; | 296 return el; |
276 }, | 297 }, |
277 | 298 |
278 /** | 299 /** |
279 * Handles keydown event from the keyboard. | 300 * Handles keydown event from the keyboard. |
280 * @private | 301 * @private |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 * Refreshes network drop-down. Should be called on language change. | 392 * Refreshes network drop-down. Should be called on language change. |
372 */ | 393 */ |
373 DropDown.refresh = function() { | 394 DropDown.refresh = function() { |
374 chrome.send('networkDropdownRefresh', []); | 395 chrome.send('networkDropdownRefresh', []); |
375 }; | 396 }; |
376 | 397 |
377 return { | 398 return { |
378 DropDown: DropDown | 399 DropDown: DropDown |
379 }; | 400 }; |
380 }); | 401 }); |
OLD | NEW |