Chromium Code Reviews| 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 |