diff options
author | altimofeev@chromium.org <altimofeev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-10 07:59:55 +0000 |
---|---|---|
committer | altimofeev@chromium.org <altimofeev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-10 07:59:55 +0000 |
commit | e2036c519b4685b13a82a1860d2c6c7326983abb (patch) | |
tree | e344da8c0ba8f96c32d766a3a647b5bb407b522a | |
parent | 6cd8666d0f2f30f20841e50e6323053ab99129bc (diff) | |
download | chromium_src-e2036c519b4685b13a82a1860d2c6c7326983abb.zip chromium_src-e2036c519b4685b13a82a1860d2c6c7326983abb.tar.gz chromium_src-e2036c519b4685b13a82a1860d2c6c7326983abb.tar.bz2 |
Makes the network dropdown keyboard accessible (focus friendly).
Also:
* fixes drop-down buttons layout.
* overlay for catching outside the menu clicks is implemented (mimics standard select control behavior).
BUG=chromium-os:18826
TEST=manual
Review URL: http://codereview.chromium.org/7550070
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96147 0039d316-1c4b-4281-b951-d872f2087c98
3 files changed, 160 insertions, 28 deletions
diff --git a/chrome/browser/resources/chromeos/login/oobe.css b/chrome/browser/resources/chromeos/login/oobe.css index 89bd4134..771a574 100644 --- a/chrome/browser/resources/chromeos/login/oobe.css +++ b/chrome/browser/resources/chromeos/login/oobe.css @@ -164,12 +164,7 @@ hr.bottom { .control-with-label { margin: 10px 0 10px 0; display: -webkit-box; -} - -.label { - margin: 5px 5px 5px 0; - padding: 5px 5px 5px 0; - width: 170px; + -webkit-box-align: start; } .menu-area { @@ -180,6 +175,12 @@ hr.bottom { width: 250px; } +.label { + margin: 5px 5px 5px 0; + padding: 5px 5px 5px 0; + width: 170px; +} + #connect { box-sizing: border-box; padding: 60px 0 0 145px; @@ -564,6 +565,7 @@ body.login-display #progress { text-indent: 4px; white-space: nowrap; width: 250px; + z-index: 10; } .dropdown-title:hover { @@ -590,7 +592,7 @@ body.login-display #progress { position: relative; top: 100%; width: 248px; - z-index: 1; + z-index: 10; } .dropdown-item-container { @@ -599,7 +601,7 @@ body.login-display #progress { padding-left: 5px; } -.dropdown-item-container:hover { +.dropdown-item-container.hover { background: #dce4fa; } @@ -659,3 +661,12 @@ html[dir=rtl] .error-message { position: absolute; text-shadow: 0 1px 1px #fff; } + +.dropdown-overlay { + bottom: 0; + left: 0; + position: fixed; + right: 0; + top: 0; + z-index: 5; +} diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_network.html b/chrome/browser/resources/chromeos/login/oobe_screen_network.html index 2ee05bc..ea116f9 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_network.html +++ b/chrome/browser/resources/chromeos/login/oobe_screen_network.html @@ -1,24 +1,20 @@ <div class="step hidden" id="connect"> <div class="control-with-label"> - <label for="language-select" i18n-content="selectLanguage" - class="label menu-control"></label> + <div i18n-content="selectLanguage" class="label menu-control"></div> <div class="menu-area"> <select id="language-select" class="menu-control"></select> </div> </div> <div class="control-with-label"> - <label for="keyboard-select" i18n-content="selectKeyboard" - class="label menu-control"></label> + <div i18n-content="selectKeyboard" class="label menu-control"></div> <div class="menu-area"> <select id="keyboard-select" class="menu-control"></select> </div> </div> <div class="control-with-label"> - <label for="networks-list" i18n-content="selectNetwork" - class="label menu-control"></label> + <div i18n-content="selectNetwork" class="label menu-control"></div> <div class="menu-area"> - <div id="networks-list" class="menu-control" - tabindex="0" role="button" aria-haspopup="true"></div> + <div id="networks-list" class="menu-control" aria-haspopup="true"></div> </div> </div> </div> diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_network.js b/chrome/browser/resources/chromeos/login/oobe_screen_network.js index 9321f49..4fe3bbc 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_network.js +++ b/chrome/browser/resources/chromeos/login/oobe_screen_network.js @@ -8,6 +8,37 @@ cr.define('oobe', function() { /** + * Creates a new container for the drop down menu items. + * @constructor + * @extends{HTMLDivElement} + */ + var DropDownContainer = cr.ui.define('div'); + + DropDownContainer.prototype = { + __proto__: HTMLDivElement.prototype, + + /** @inheritDoc */ + decorate: function() { + this.classList.add('dropdown-container'); + // Selected item in the menu list. + this.selectedItem = null; + // First item which could be selected. + this.firstItem = null; + }, + + /** + * Selects new item. + * @param {!Object} selectedItem Item to be selected. + */ + selectItem: function(selectedItem) { + if (this.selectedItem) + this.selectedItem.classList.remove('hover'); + selectedItem.classList.add('hover'); + this.selectedItem = selectedItem; + } + }; + + /** * Creates a new DropDown div. * @constructor * @extends {HTMLDivElement} @@ -21,13 +52,12 @@ cr.define('oobe', function() { /** @inheritDoc */ decorate: function() { + this.appendChild(this.createOverlay_()); this.appendChild(this.createTitle_()); + this.appendChild(new DropDownContainer()); - // Create menu items container. - var container = this.ownerDocument.createElement('div') - container.classList.add('dropdown-container'); - this.appendChild(container); this.isShown = false; + this.addEventListener('keydown', this.keyDownHandler_); }, /** @@ -35,7 +65,7 @@ cr.define('oobe', function() { * @type {bool} Whether menu element is shown. */ get isShown() { - return !this.lastElementChild.hidden; + return !this.container.hidden; }, /** @@ -43,7 +73,24 @@ cr.define('oobe', function() { * @param {bool} show New visibility state for dropdown menu. */ set isShown(show) { - this.lastElementChild.hidden = !show; + this.firstElementChild.hidden = !show; + this.container.hidden = !show; + if (show) + this.container.selectItem(this.container.firstItem); + }, + + /** + * Returns title button. + */ + get titleButton() { + return this.childNodes[1]; + }, + + /** + * Returns container of the menu items. + */ + get container() { + return this.lastElementChild; }, /** @@ -53,7 +100,7 @@ cr.define('oobe', function() { */ setTitle: function(title, icon) { // TODO(nkostylev): Icon support for dropdown title. - this.firstElementChild.textContent = title; + this.titleButton.textContent = title; }, /** @@ -61,19 +108,21 @@ cr.define('oobe', function() { * @param {Array} items Dropdown items array. */ setItems: function(items) { - var container = this.lastElementChild; - container.innerHTML = ''; + this.container.innerHTML = ''; + this.container.firstItem = null; + this.container.selectedItem = null; for (var i = 0; i < items.length; ++i) { var item = items[i]; if ('sub' in item) { // Workaround for submenus, add items on top level. // TODO(altimofeev): support submenus. for (var j = 0; j < item.sub.length; ++j) - this.createItem_(container, item.sub[j]); + this.createItem_(this.container, item.sub[j]); continue; } - this.createItem_(container, item); + this.createItem_(this.container, item); } + this.container.selectItem(this.container.firstItem); }, /** @@ -120,13 +169,34 @@ cr.define('oobe', function() { var item = this.lastElementChild; if (item.iid < -1 || item.classList.contains('disabled-item')) return; - item.controller.isShown = !item.controller.isShown; + item.controller.isShown = false; if (item.iid >= 0) chrome.send('networkItemChosen', [item.iid]); }); + wrapperDiv.addEventListener('mouseover', function f(e) { + this.parentNode.selectItem(this); + }); itemElement = wrapperDiv; } container.appendChild(itemElement); + if (!container.firstItem && item.id >= 0) { + container.firstItem = itemElement; + } + }, + + /** + * Creates dropdown overlay element, which catches outside clicks. + * @type {HTMLElement} + * @private + */ + createOverlay_: function() { + var overlay = this.ownerDocument.createElement('div'); + overlay.classList.add('dropdown-overlay'); + overlay.addEventListener('click', function() { + this.parentNode.titleButton.focus(); + this.parentNode.isShown = false; + }); + return overlay; }, /** @@ -139,10 +209,65 @@ cr.define('oobe', function() { el.classList.add('dropdown-title'); el.iid = -1; el.controller = this; + el.enterPressed = false; + el.addEventListener('click', function f(e) { + this.focus(); this.controller.isShown = !this.controller.isShown; + + if (this.enterPressed) { + this.enterPressed = false; + if (!this.controller.isShown) { + var item = this.controller.container.selectedItem.lastElementChild; + if (item.iid >= 0 && !item.classList.contains('disabled-item')) + chrome.send('networkItemChosen', [item.iid]); + } + } }); return el; + }, + + /** + * Handles keydown event from the keyboard. + * @private + * @param {!Event} e Keydown event. + */ + keyDownHandler_: function(e) { + if (!this.isShown) + return; + var selected = this.container.selectedItem; + switch(e.keyCode) { + case 38: { // Key up. + do { + selected = selected.previousSibling; + if (!selected) + selected = this.container.lastElementChild; + } while (selected.iid < 0); + this.container.selectItem(selected); + break; + } + case 40: { // Key down. + do { + selected = selected.nextSibling; + if (!selected) + selected = this.container.firstItem; + } while (selected.iid < 0); + this.container.selectItem(selected); + break; + } + case 27: { // Esc. + this.isShown = false; + break; + } + case 9: { // Tab. + this.isShown = false; + break; + } + case 13: { // Enter. + this.titleButton.enterPressed = true; + break; + } + }; } }; |