Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: chrome/browser/resources/chromeos/login/oobe_screen_network.js

Issue 7550070: Makes the network dropdown keyboard accessible (focus friendly). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: code review Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/resources/chromeos/login/oobe_screen_network.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 Oobe network screen implementation. 6 * @fileoverview Oobe network screen implementation.
7 */ 7 */
8 8
9 cr.define('oobe', function() { 9 cr.define('oobe', function() {
10 /** 10 /**
11 * Creates a new container for the drop down menu items.
12 * @constructor
13 * @extends{HTMLDivElement}
14 */
15 var DropDownContainer = cr.ui.define('div');
16
17 DropDownContainer.prototype = {
18 __proto__: HTMLDivElement.prototype,
19
20 /** @inheritDoc */
21 decorate: function() {
22 this.classList.add('dropdown-container');
23 // Selected item in the menu list.
24 this.selectedItem = null;
25 // First item which could be selected.
26 this.firstItem = null;
27 },
28
29 /**
30 * Selects new item.
31 * @param {!Object} selectedItem Item to be selected.
32 */
33 selectItem: function(selectedItem) {
34 if (this.selectedItem)
35 this.selectedItem.classList.remove('hover');
36 selectedItem.classList.add('hover');
37 this.selectedItem = selectedItem;
38 }
39 };
40
41 /**
11 * Creates a new DropDown div. 42 * Creates a new DropDown div.
12 * @constructor 43 * @constructor
13 * @extends {HTMLDivElement} 44 * @extends {HTMLDivElement}
14 */ 45 */
15 var DropDown = cr.ui.define('div'); 46 var DropDown = cr.ui.define('div');
16 47
17 DropDown.ITEM_DIVIDER_ID = -2; 48 DropDown.ITEM_DIVIDER_ID = -2;
18 49
19 DropDown.prototype = { 50 DropDown.prototype = {
20 __proto__: HTMLDivElement.prototype, 51 __proto__: HTMLDivElement.prototype,
21 52
22 /** @inheritDoc */ 53 /** @inheritDoc */
23 decorate: function() { 54 decorate: function() {
55 this.appendChild(this.createOverlay_());
24 this.appendChild(this.createTitle_()); 56 this.appendChild(this.createTitle_());
57 this.appendChild(new DropDownContainer());
25 58
26 // Create menu items container.
27 var container = this.ownerDocument.createElement('div')
28 container.classList.add('dropdown-container');
29 this.appendChild(container);
30 this.isShown = false; 59 this.isShown = false;
60 this.addEventListener('keydown', this.keyDownHandler_);
31 }, 61 },
32 62
33 /** 63 /**
34 * Returns true if dropdown menu is shown. 64 * Returns true if dropdown menu is shown.
35 * @type {bool} Whether menu element is shown. 65 * @type {bool} Whether menu element is shown.
36 */ 66 */
37 get isShown() { 67 get isShown() {
38 return !this.lastElementChild.hidden; 68 return !this.container.hidden;
39 }, 69 },
40 70
41 /** 71 /**
42 * Sets dropdown menu visibility. 72 * Sets dropdown menu visibility.
43 * @param {bool} show New visibility state for dropdown menu. 73 * @param {bool} show New visibility state for dropdown menu.
44 */ 74 */
45 set isShown(show) { 75 set isShown(show) {
46 this.lastElementChild.hidden = !show; 76 this.firstElementChild.hidden = !show;
77 this.container.hidden = !show;
78 if (show)
79 this.container.selectItem(this.container.firstItem);
47 }, 80 },
48 81
49 /** 82 /**
83 * Returns title button.
84 */
85 get titleButton() {
86 return this.childNodes[1];
87 },
88
89 /**
90 * Returns container of the menu items.
91 */
92 get container() {
93 return this.lastElementChild;
94 },
95
96 /**
50 * Sets title and icon. 97 * Sets title and icon.
51 * @param {string} title Text on dropdown. 98 * @param {string} title Text on dropdown.
52 * @param {string} icon Icon in dataURL format. 99 * @param {string} icon Icon in dataURL format.
53 */ 100 */
54 setTitle: function(title, icon) { 101 setTitle: function(title, icon) {
55 // TODO(nkostylev): Icon support for dropdown title. 102 // TODO(nkostylev): Icon support for dropdown title.
56 this.firstElementChild.textContent = title; 103 this.titleButton.textContent = title;
57 }, 104 },
58 105
59 /** 106 /**
60 * Sets dropdown items. 107 * Sets dropdown items.
61 * @param {Array} items Dropdown items array. 108 * @param {Array} items Dropdown items array.
62 */ 109 */
63 setItems: function(items) { 110 setItems: function(items) {
64 var container = this.lastElementChild; 111 this.container.innerHTML = '';
65 container.innerHTML = ''; 112 this.container.firstItem = null;
113 this.container.selectedItem = null;
66 for (var i = 0; i < items.length; ++i) { 114 for (var i = 0; i < items.length; ++i) {
67 var item = items[i]; 115 var item = items[i];
68 if ('sub' in item) { 116 if ('sub' in item) {
69 // Workaround for submenus, add items on top level. 117 // Workaround for submenus, add items on top level.
70 // TODO(altimofeev): support submenus. 118 // TODO(altimofeev): support submenus.
71 for (var j = 0; j < item.sub.length; ++j) 119 for (var j = 0; j < item.sub.length; ++j)
72 this.createItem_(container, item.sub[j]); 120 this.createItem_(this.container, item.sub[j]);
73 continue; 121 continue;
74 } 122 }
75 this.createItem_(container, item); 123 this.createItem_(this.container, item);
76 } 124 }
125 this.container.selectItem(this.container.firstItem);
77 }, 126 },
78 127
79 /** 128 /**
80 * Creates dropdown item element and adds into container. 129 * Creates dropdown item element and adds into container.
81 * @param {HTMLElement} container Container where item is added. 130 * @param {HTMLElement} container Container where item is added.
82 * @param {!Object} item Item to be added. 131 * @param {!Object} item Item to be added.
83 * @private 132 * @private
84 */ 133 */
85 createItem_ : function(container, item) { 134 createItem_ : function(container, item) {
86 var itemContentElement; 135 var itemContentElement;
(...skipping 26 matching lines...) Expand all
113 wrapperDiv.classList.add('dropdown-item-container'); 162 wrapperDiv.classList.add('dropdown-item-container');
114 var imageDiv = this.ownerDocument.createElement('div'); 163 var imageDiv = this.ownerDocument.createElement('div');
115 imageDiv.classList.add('dropdown-image'); 164 imageDiv.classList.add('dropdown-image');
116 imageDiv.appendChild(image); 165 imageDiv.appendChild(image);
117 wrapperDiv.appendChild(imageDiv); 166 wrapperDiv.appendChild(imageDiv);
118 wrapperDiv.appendChild(itemElement); 167 wrapperDiv.appendChild(itemElement);
119 wrapperDiv.addEventListener('click', function f(e) { 168 wrapperDiv.addEventListener('click', function f(e) {
120 var item = this.lastElementChild; 169 var item = this.lastElementChild;
121 if (item.iid < -1 || item.classList.contains('disabled-item')) 170 if (item.iid < -1 || item.classList.contains('disabled-item'))
122 return; 171 return;
123 item.controller.isShown = !item.controller.isShown; 172 item.controller.isShown = false;
124 if (item.iid >= 0) 173 if (item.iid >= 0)
125 chrome.send('networkItemChosen', [item.iid]); 174 chrome.send('networkItemChosen', [item.iid]);
126 }); 175 });
176 wrapperDiv.addEventListener('mouseover', function f(e) {
177 this.parentNode.selectItem(this);
178 });
127 itemElement = wrapperDiv; 179 itemElement = wrapperDiv;
128 } 180 }
129 container.appendChild(itemElement); 181 container.appendChild(itemElement);
182 if (!container.firstItem && item.id >= 0) {
183 container.firstItem = itemElement;
184 }
130 }, 185 },
131 186
132 /** 187 /**
188 * Creates dropdown overlay element, which catches outside clicks.
189 * @type {HTMLElement}
190 * @private
191 */
192 createOverlay_: function() {
193 var overlay = this.ownerDocument.createElement('div');
194 overlay.classList.add('dropdown-overlay');
195 overlay.addEventListener('click', function() {
196 this.parentNode.titleButton.focus();
197 this.parentNode.isShown = false;
198 });
199 return overlay;
200 },
201
202 /**
133 * Creates dropdown title element. 203 * Creates dropdown title element.
134 * @type {HTMLElement} 204 * @type {HTMLElement}
135 * @private 205 * @private
136 */ 206 */
137 createTitle_: function() { 207 createTitle_: function() {
138 var el = this.ownerDocument.createElement('button'); 208 var el = this.ownerDocument.createElement('button');
139 el.classList.add('dropdown-title'); 209 el.classList.add('dropdown-title');
140 el.iid = -1; 210 el.iid = -1;
141 el.controller = this; 211 el.controller = this;
212 el.enterPressed = false;
213
142 el.addEventListener('click', function f(e) { 214 el.addEventListener('click', function f(e) {
215 this.focus();
143 this.controller.isShown = !this.controller.isShown; 216 this.controller.isShown = !this.controller.isShown;
217
218 if (this.enterPressed) {
219 this.enterPressed = false;
220 if (!this.controller.isShown) {
221 var item = this.controller.container.selectedItem.lastElementChild;
222 if (item.iid >= 0 && !item.classList.contains('disabled-item'))
223 chrome.send('networkItemChosen', [item.iid]);
224 }
225 }
144 }); 226 });
145 return el; 227 return el;
228 },
229
230 /**
231 * Handles keydown event from the keyboard.
232 * @private
233 * @param {!Event} e Keydown event.
234 */
235 keyDownHandler_: function(e) {
236 if (!this.isShown)
237 return;
238 var selected = this.container.selectedItem;
239 switch(e.keyCode) {
240 case 38: { // Key up.
241 do {
242 selected = selected.previousSibling;
243 if (!selected)
244 selected = this.container.lastElementChild;
245 } while (selected.iid < 0);
246 this.container.selectItem(selected);
247 break;
248 }
249 case 40: { // Key down.
250 do {
251 selected = selected.nextSibling;
252 if (!selected)
253 selected = this.container.firstItem;
254 } while (selected.iid < 0);
255 this.container.selectItem(selected);
256 break;
257 }
258 case 27: { // Esc.
259 this.isShown = false;
260 break;
261 }
262 case 9: { // Tab.
263 this.isShown = false;
264 break;
265 }
266 case 13: { // Enter.
267 this.titleButton.enterPressed = true;
268 break;
269 }
270 };
146 } 271 }
147 }; 272 };
148 273
149 /** 274 /**
150 * Creates a new oobe screen div. 275 * Creates a new oobe screen div.
151 * @constructor 276 * @constructor
152 * @extends {HTMLDivElement} 277 * @extends {HTMLDivElement}
153 */ 278 */
154 var NetworkScreen = cr.ui.define('div'); 279 var NetworkScreen = cr.ui.define('div');
155 280
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 }; 358 };
234 359
235 NetworkScreen.updateNetworkTitle = function(title, icon) { 360 NetworkScreen.updateNetworkTitle = function(title, icon) {
236 $('connect').updateNetworkTitle(title, icon); 361 $('connect').updateNetworkTitle(title, icon);
237 }; 362 };
238 363
239 return { 364 return {
240 NetworkScreen: NetworkScreen 365 NetworkScreen: NetworkScreen
241 }; 366 };
242 }); 367 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/chromeos/login/oobe_screen_network.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698