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 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_()); |
25 | 57 |
26 // Create menu items container. | 58 // Create menu items container. |
27 var container = this.ownerDocument.createElement('div') | 59 var container = this.ownerDocument.createElement('div'); |
28 container.classList.add('dropdown-container'); | 60 DropDownContainer.decorate(container); |
xiyuan
2011/08/09 16:43:39
nit: think you could combine line 59-60 like this:
altimofeev
2011/08/09 17:17:30
Done.
| |
29 this.appendChild(container); | 61 this.appendChild(container); |
62 | |
30 this.isShown = false; | 63 this.isShown = false; |
64 this.addEventListener('keydown', this.keyDownHandler_); | |
31 }, | 65 }, |
32 | 66 |
33 /** | 67 /** |
34 * Returns true if dropdown menu is shown. | 68 * Returns true if dropdown menu is shown. |
35 * @type {bool} Whether menu element is shown. | 69 * @type {bool} Whether menu element is shown. |
36 */ | 70 */ |
37 get isShown() { | 71 get isShown() { |
38 return !this.lastElementChild.hidden; | 72 return !this.container.hidden; |
39 }, | 73 }, |
40 | 74 |
41 /** | 75 /** |
42 * Sets dropdown menu visibility. | 76 * Sets dropdown menu visibility. |
43 * @param {bool} show New visibility state for dropdown menu. | 77 * @param {bool} show New visibility state for dropdown menu. |
44 */ | 78 */ |
45 set isShown(show) { | 79 set isShown(show) { |
46 this.lastElementChild.hidden = !show; | 80 this.firstElementChild.hidden = !show; |
81 this.container.hidden = !show; | |
82 if (show) | |
83 this.container.selectItem(this.container.firstItem); | |
47 }, | 84 }, |
48 | 85 |
49 /** | 86 /** |
87 * Returns title button. | |
88 */ | |
89 get titleButton() { | |
90 return this.childNodes[1]; | |
91 }, | |
92 | |
93 /** | |
94 * Returns container of the menu items. | |
95 */ | |
96 get container() { | |
97 return this.lastElementChild; | |
98 }, | |
99 | |
100 /** | |
50 * Sets title and icon. | 101 * Sets title and icon. |
51 * @param {string} title Text on dropdown. | 102 * @param {string} title Text on dropdown. |
52 * @param {string} icon Icon in dataURL format. | 103 * @param {string} icon Icon in dataURL format. |
53 */ | 104 */ |
54 setTitle: function(title, icon) { | 105 setTitle: function(title, icon) { |
55 // TODO(nkostylev): Icon support for dropdown title. | 106 // TODO(nkostylev): Icon support for dropdown title. |
56 this.firstElementChild.textContent = title; | 107 this.titleButton.textContent = title; |
57 }, | 108 }, |
58 | 109 |
59 /** | 110 /** |
60 * Sets dropdown items. | 111 * Sets dropdown items. |
61 * @param {Array} items Dropdown items array. | 112 * @param {Array} items Dropdown items array. |
62 */ | 113 */ |
63 setItems: function(items) { | 114 setItems: function(items) { |
64 var container = this.lastElementChild; | 115 this.container.innerHTML = ''; |
65 container.innerHTML = ''; | 116 this.container.firstItem = null; |
117 this.container.selectedItem = null; | |
66 for (var i = 0; i < items.length; ++i) { | 118 for (var i = 0; i < items.length; ++i) { |
67 var item = items[i]; | 119 var item = items[i]; |
68 if ('sub' in item) { | 120 if ('sub' in item) { |
69 // Workaround for submenus, add items on top level. | 121 // Workaround for submenus, add items on top level. |
70 // TODO(altimofeev): support submenus. | 122 // TODO(altimofeev): support submenus. |
71 for (var j = 0; j < item.sub.length; ++j) | 123 for (var j = 0; j < item.sub.length; ++j) |
72 this.createItem_(container, item.sub[j]); | 124 this.createItem_(this.container, item.sub[j]); |
73 continue; | 125 continue; |
74 } | 126 } |
75 this.createItem_(container, item); | 127 this.createItem_(this.container, item); |
76 } | 128 } |
129 this.container.selectItem(this.container.firstItem); | |
77 }, | 130 }, |
78 | 131 |
79 /** | 132 /** |
80 * Creates dropdown item element and adds into container. | 133 * Creates dropdown item element and adds into container. |
81 * @param {HTMLElement} container Container where item is added. | 134 * @param {HTMLElement} container Container where item is added. |
82 * @param {!Object} item Item to be added. | 135 * @param {!Object} item Item to be added. |
83 * @private | 136 * @private |
84 */ | 137 */ |
85 createItem_ : function(container, item) { | 138 createItem_ : function(container, item) { |
86 var itemContentElement; | 139 var itemContentElement; |
(...skipping 26 matching lines...) Expand all Loading... | |
113 wrapperDiv.classList.add('dropdown-item-container'); | 166 wrapperDiv.classList.add('dropdown-item-container'); |
114 var imageDiv = this.ownerDocument.createElement('div'); | 167 var imageDiv = this.ownerDocument.createElement('div'); |
115 imageDiv.classList.add('dropdown-image'); | 168 imageDiv.classList.add('dropdown-image'); |
116 imageDiv.appendChild(image); | 169 imageDiv.appendChild(image); |
117 wrapperDiv.appendChild(imageDiv); | 170 wrapperDiv.appendChild(imageDiv); |
118 wrapperDiv.appendChild(itemElement); | 171 wrapperDiv.appendChild(itemElement); |
119 wrapperDiv.addEventListener('click', function f(e) { | 172 wrapperDiv.addEventListener('click', function f(e) { |
120 var item = this.lastElementChild; | 173 var item = this.lastElementChild; |
121 if (item.iid < -1 || item.classList.contains('disabled-item')) | 174 if (item.iid < -1 || item.classList.contains('disabled-item')) |
122 return; | 175 return; |
123 item.controller.isShown = !item.controller.isShown; | 176 item.controller.isShown = false; |
124 if (item.iid >= 0) | 177 if (item.iid >= 0) |
125 chrome.send('networkItemChosen', [item.iid]); | 178 chrome.send('networkItemChosen', [item.iid]); |
126 }); | 179 }); |
180 wrapperDiv.addEventListener('mouseover', function f(e) { | |
181 this.parentNode.selectItem(this); | |
182 }); | |
127 itemElement = wrapperDiv; | 183 itemElement = wrapperDiv; |
128 } | 184 } |
129 container.appendChild(itemElement); | 185 container.appendChild(itemElement); |
186 if (!container.firstItem && item.id >= 0) { | |
187 container.firstItem = itemElement; | |
188 } | |
130 }, | 189 }, |
131 | 190 |
132 /** | 191 /** |
192 * Creates dropdown overlay element, which catches outside clicks. | |
193 * @type {HTMLElement} | |
194 * @private | |
195 */ | |
196 createOverlay_: function() { | |
197 var overlay = this.ownerDocument.createElement('div'); | |
198 overlay.classList.add('dropdown-overlay'); | |
199 overlay.addEventListener('click', function() { | |
200 this.parentNode.titleButton.focus(); | |
201 this.parentNode.isShown = false; | |
202 }); | |
203 return overlay; | |
204 }, | |
205 | |
206 /** | |
133 * Creates dropdown title element. | 207 * Creates dropdown title element. |
134 * @type {HTMLElement} | 208 * @type {HTMLElement} |
135 * @private | 209 * @private |
136 */ | 210 */ |
137 createTitle_: function() { | 211 createTitle_: function() { |
138 var el = this.ownerDocument.createElement('button'); | 212 var el = this.ownerDocument.createElement('button'); |
139 el.classList.add('dropdown-title'); | 213 el.classList.add('dropdown-title'); |
140 el.iid = -1; | 214 el.iid = -1; |
141 el.controller = this; | 215 el.controller = this; |
216 el.enterPressed = false; | |
217 | |
142 el.addEventListener('click', function f(e) { | 218 el.addEventListener('click', function f(e) { |
219 this.focus(); | |
xiyuan
2011/08/09 16:43:39
Think a focusable element should automatically get
altimofeev
2011/08/09 17:17:30
It doesn't get the focus, when menu is being opene
| |
143 this.controller.isShown = !this.controller.isShown; | 220 this.controller.isShown = !this.controller.isShown; |
221 | |
222 if (this.enterPressed) { | |
xiyuan
2011/08/09 16:43:39
Does this mean user needs to hit "enter" on the dr
altimofeev
2011/08/09 17:17:30
Not exactly. There are 3 cases:
1. User clicks on
| |
223 this.enterPressed = false; | |
224 if (!this.controller.isShown) { | |
225 var item = this.controller.container.selectedItem.lastElementChild; | |
226 if (item.iid >= 0 && !item.classList.contains('disabled-item')) | |
227 chrome.send('networkItemChosen', [item.iid]); | |
228 } | |
229 } | |
144 }); | 230 }); |
145 return el; | 231 return el; |
232 }, | |
233 | |
234 /** | |
235 * Handles keydown event from the keyboard. | |
236 * @private | |
237 * @param {!Object} e Keydown event. | |
xiyuan
2011/08/09 16:43:39
nit: {!Event}
altimofeev
2011/08/09 17:17:30
Done.
| |
238 */ | |
239 keyDownHandler_: function(e) { | |
240 if (!this.isShown) | |
241 return; | |
242 var selected = this.container.selectedItem; | |
243 switch(e.keyCode) { | |
244 case 38: { // Key up. | |
245 do { | |
246 selected = selected.previousSibling; | |
247 if (!selected) | |
248 selected = this.container.lastElementChild; | |
249 } while (selected.iid < 0); | |
250 this.container.selectItem(selected); | |
251 break; | |
252 } | |
253 case 40: { // Key down. | |
254 do { | |
255 selected = selected.nextSibling; | |
256 if (!selected) | |
257 selected = this.container.firstItem; | |
258 } while (selected.iid < 0); | |
259 this.container.selectItem(selected); | |
260 break; | |
261 } | |
262 case 27: { // Esc. | |
263 this.isShown = false; | |
264 break; | |
265 } | |
266 case 9: { // Tab. | |
xiyuan
2011/08/09 16:43:39
We should do this in "blur" handler instead of cap
altimofeev
2011/08/09 17:17:30
1. As I have stated, button loses focus when menu
| |
267 this.isShown = false; | |
268 break; | |
269 } | |
270 case 13: { // Enter. | |
271 this.titleButton.enterPressed = true; | |
272 break; | |
273 } | |
274 }; | |
146 } | 275 } |
147 }; | 276 }; |
148 | 277 |
149 /** | 278 /** |
150 * Creates a new oobe screen div. | 279 * Creates a new oobe screen div. |
151 * @constructor | 280 * @constructor |
152 * @extends {HTMLDivElement} | 281 * @extends {HTMLDivElement} |
153 */ | 282 */ |
154 var NetworkScreen = cr.ui.define('div'); | 283 var NetworkScreen = cr.ui.define('div'); |
155 | 284 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 }; | 362 }; |
234 | 363 |
235 NetworkScreen.updateNetworkTitle = function(title, icon) { | 364 NetworkScreen.updateNetworkTitle = function(title, icon) { |
236 $('connect').updateNetworkTitle(title, icon); | 365 $('connect').updateNetworkTitle(title, icon); |
237 }; | 366 }; |
238 | 367 |
239 return { | 368 return { |
240 NetworkScreen: NetworkScreen | 369 NetworkScreen: NetworkScreen |
241 }; | 370 }; |
242 }); | 371 }); |
OLD | NEW |