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

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: 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 DropDown div. 11 * Creates a new DropDown div.
12 * @constructor 12 * @constructor
13 * @extends {HTMLDivElement} 13 * @extends {HTMLDivElement}
14 */ 14 */
15 var DropDown = cr.ui.define('div'); 15 var DropDown = cr.ui.define('div');
16 16
17 DropDown.ITEM_DIVIDER_ID = -2; 17 DropDown.ITEM_DIVIDER_ID = -2;
18 18
19 DropDown.prototype = { 19 DropDown.prototype = {
20 __proto__: HTMLDivElement.prototype, 20 __proto__: HTMLDivElement.prototype,
21 21
22 /** @inheritDoc */ 22 /** @inheritDoc */
23 decorate: function() { 23 decorate: function() {
24 // Create overlay to catch outside clicks.
25 var overlay = this.ownerDocument.createElement('div');
26 overlay.classList.add('dropdown-overlay');
27 overlay.addEventListener('click', function() {
28 this.parentNode.childNodes[1].focus();
xiyuan 2011/08/08 20:07:43 Let's add two getters for title buttone and dropdo
altimofeev 2011/08/09 10:32:30 Done.
29 this.parentNode.isShown = false;
30 });
31 this.appendChild(overlay);
32
24 this.appendChild(this.createTitle_()); 33 this.appendChild(this.createTitle_());
25 34
26 // Create menu items container. 35 // Create menu items container.
27 var container = this.ownerDocument.createElement('div') 36 var container = this.ownerDocument.createElement('div');
xiyuan 2011/08/08 20:07:43 recommend to wrap the container into a class.
altimofeev 2011/08/09 10:32:30 Done.
28 container.classList.add('dropdown-container'); 37 container.classList.add('dropdown-container');
38
39 // Selected item in the menu list.
40 container.selectedItem = null;
41
42 container.selectItem = function (selectedItem) {
43 if (container.selectedItem)
44 container.selectedItem.classList.remove('hover');
45 selectedItem.classList.add('hover');
46 container.selectedItem = selectedItem;
47 };
48
29 this.appendChild(container); 49 this.appendChild(container);
30 this.isShown = false; 50 this.isShown = false;
51
52 // Handle pressing of the up/down keys.
53 this.addEventListener('keydown', function (e) {
xiyuan 2011/08/08 20:07:43 Could we put the logic into its own function since
altimofeev 2011/08/09 10:32:30 Done.
54 if (!this.isShown)
55 return;
56 var container = this.lastChild;
57 var selected = container.selectedItem;
58 switch(e.keyCode) {
xiyuan 2011/08/08 20:07:43 do we need to handle "enter" key as well?
altimofeev 2011/08/09 10:32:30 tl;dr. Done. Enter is handled by JS directly, sin
59 case 38: { // Key up.
60 do {
61 selected = selected.previousSibling;
62 if (!selected)
63 selected = container.lastChild;
64 } while (selected.iid < 0);
65 container.selectItem(selected);
66 break;
67 }
68 case 40: { // Key down.
69 do {
70 selected = selected.nextSibling;
71 if (!selected)
72 selected = container.firstItem;
73 } while (selected.iid < 0);
74 container.selectItem(selected);
75 break;
76 }
77 case 27: { // Esc.
78 this.isShown = false;
79 break;
80 }
81 case 9: { // Tab.
82 this.isShown = false;
83 break;
84 }
85 }
86 });
31 }, 87 },
32 88
33 /** 89 /**
34 * Returns true if dropdown menu is shown. 90 * Returns true if dropdown menu is shown.
35 * @type {bool} Whether menu element is shown. 91 * @type {bool} Whether menu element is shown.
36 */ 92 */
37 get isShown() { 93 get isShown() {
38 return !this.lastElementChild.hidden; 94 return !this.lastElementChild.hidden;
39 }, 95 },
40 96
41 /** 97 /**
42 * Sets dropdown menu visibility. 98 * Sets dropdown menu visibility.
43 * @param {bool} show New visibility state for dropdown menu. 99 * @param {bool} show New visibility state for dropdown menu.
44 */ 100 */
45 set isShown(show) { 101 set isShown(show) {
102 if (show) {
103 this.lastElementChild.selectItem(this.lastElementChild.firstItem);
104 }
xiyuan 2011/08/08 20:07:43 nit: no need for enclosing {} for one line branch.
altimofeev 2011/08/09 10:32:30 Done.
46 this.lastElementChild.hidden = !show; 105 this.lastElementChild.hidden = !show;
106 this.firstElementChild.hidden = !show;
47 }, 107 },
48 108
49 /** 109 /**
50 * Sets title and icon. 110 * Sets title and icon.
51 * @param {string} title Text on dropdown. 111 * @param {string} title Text on dropdown.
52 * @param {string} icon Icon in dataURL format. 112 * @param {string} icon Icon in dataURL format.
53 */ 113 */
54 setTitle: function(title, icon) { 114 setTitle: function(title, icon) {
55 // TODO(nkostylev): Icon support for dropdown title. 115 // TODO(nkostylev): Icon support for dropdown title.
56 this.firstElementChild.textContent = title; 116 this.childNodes[1].textContent = title;
57 }, 117 },
58 118
59 /** 119 /**
60 * Sets dropdown items. 120 * Sets dropdown items.
61 * @param {Array} items Dropdown items array. 121 * @param {Array} items Dropdown items array.
62 */ 122 */
63 setItems: function(items) { 123 setItems: function(items) {
64 var container = this.lastElementChild; 124 var container = this.lastElementChild;
65 container.innerHTML = ''; 125 container.innerHTML = '';
126 // First item in the menu list.
127 container.firstItem = null;
xiyuan 2011/08/08 20:07:43 clear container.selectedItem as well?
altimofeev 2011/08/09 10:32:30 Good point, this is useful for the case, when the
66 for (var i = 0; i < items.length; ++i) { 128 for (var i = 0; i < items.length; ++i) {
67 var item = items[i]; 129 var item = items[i];
68 if ('sub' in item) { 130 if ('sub' in item) {
69 // Workaround for submenus, add items on top level. 131 // Workaround for submenus, add items on top level.
70 // TODO(altimofeev): support submenus. 132 // TODO(altimofeev): support submenus.
71 for (var j = 0; j < item.sub.length; ++j) 133 for (var j = 0; j < item.sub.length; ++j)
72 this.createItem_(container, item.sub[j]); 134 this.createItem_(container, item.sub[j]);
73 continue; 135 continue;
74 } 136 }
75 this.createItem_(container, item); 137 this.createItem_(container, item);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 wrapperDiv.classList.add('dropdown-item-container'); 175 wrapperDiv.classList.add('dropdown-item-container');
114 var imageDiv = this.ownerDocument.createElement('div'); 176 var imageDiv = this.ownerDocument.createElement('div');
115 imageDiv.classList.add('dropdown-image'); 177 imageDiv.classList.add('dropdown-image');
116 imageDiv.appendChild(image); 178 imageDiv.appendChild(image);
117 wrapperDiv.appendChild(imageDiv); 179 wrapperDiv.appendChild(imageDiv);
118 wrapperDiv.appendChild(itemElement); 180 wrapperDiv.appendChild(itemElement);
119 wrapperDiv.addEventListener('click', function f(e) { 181 wrapperDiv.addEventListener('click', function f(e) {
120 var item = this.lastElementChild; 182 var item = this.lastElementChild;
121 if (item.iid < -1 || item.classList.contains('disabled-item')) 183 if (item.iid < -1 || item.classList.contains('disabled-item'))
122 return; 184 return;
123 item.controller.isShown = !item.controller.isShown; 185 item.controller.isShown = false;
124 if (item.iid >= 0) 186 if (item.iid >= 0)
125 chrome.send('networkItemChosen', [item.iid]); 187 chrome.send('networkItemChosen', [item.iid]);
126 }); 188 });
189 wrapperDiv.addEventListener('mouseover', function f(e) {
190 this.parentNode.selectItem(this);
191 });
127 itemElement = wrapperDiv; 192 itemElement = wrapperDiv;
128 } 193 }
129 container.appendChild(itemElement); 194 container.appendChild(itemElement);
195 if (!container.firstItem && item.id >= 0) {
196 container.firstItem = itemElement;
197 }
130 }, 198 },
131 199
132 /** 200 /**
133 * Creates dropdown title element. 201 * Creates dropdown title element.
134 * @type {HTMLElement} 202 * @type {HTMLElement}
135 * @private 203 * @private
136 */ 204 */
137 createTitle_: function() { 205 createTitle_: function() {
138 var el = this.ownerDocument.createElement('button'); 206 var el = this.ownerDocument.createElement('button');
139 el.classList.add('dropdown-title'); 207 el.classList.add('dropdown-title');
208 el.id = 'dropdown-title-button';
140 el.iid = -1; 209 el.iid = -1;
141 el.controller = this; 210 el.controller = this;
211 el.mouseDown = false;
212
213 // Only occurs with mouse click.
214 el.addEventListener('mousedown', function f(e) {
215 this.controller.isShown = !this.controller.isShown;
216 this.mouseDown = true;
217 // TODO(altimofeev): avoid this hack.
218 setTimeout("$('dropdown-title-button').focus();", 1);
219 });
220
142 el.addEventListener('click', function f(e) { 221 el.addEventListener('click', function f(e) {
222 if (this.mouseDown) {
223 this.mouseDown = false;
224 return;
225 }
143 this.controller.isShown = !this.controller.isShown; 226 this.controller.isShown = !this.controller.isShown;
227
228 if (!this.controller.isShown) {
229 var item = this.controller.lastChild.selectedItem.lastChild;
230 if (item.iid >= 0 && !item.classList.contains('disabled-item'))
231 chrome.send('networkItemChosen', [item.iid]);
232 }
144 }); 233 });
145 return el; 234 return el;
146 } 235 }
147 }; 236 };
148 237
149 /** 238 /**
150 * Creates a new oobe screen div. 239 * Creates a new oobe screen div.
151 * @constructor 240 * @constructor
152 * @extends {HTMLDivElement} 241 * @extends {HTMLDivElement}
153 */ 242 */
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 }; 322 };
234 323
235 NetworkScreen.updateNetworkTitle = function(title, icon) { 324 NetworkScreen.updateNetworkTitle = function(title, icon) {
236 $('connect').updateNetworkTitle(title, icon); 325 $('connect').updateNetworkTitle(title, icon);
237 }; 326 };
238 327
239 return { 328 return {
240 NetworkScreen: NetworkScreen 329 NetworkScreen: NetworkScreen
241 }; 330 };
242 }); 331 });
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