Chromium Code Reviews| Index: chrome/browser/resources/options/options_page.js |
| diff --git a/chrome/browser/resources/options/options_page.js b/chrome/browser/resources/options/options_page.js |
| index 715de30257100d1aecf729b0d29372c53c47718b..51ba5729676236301bd8387221aa880b3d3b61ca 100644 |
| --- a/chrome/browser/resources/options/options_page.js |
| +++ b/chrome/browser/resources/options/options_page.js |
| @@ -129,11 +129,20 @@ cr.define('options', function() { |
| * @private |
| */ |
| OptionsPage.isOverlayVisible_ = function() { |
| + return this.getVisibleOverlay_() != null; |
| + }; |
| + |
| + /** |
| + * Returns the currently visible overlay, or null if no page is visible. |
| + * @return {OptionPage} The visible overlay. |
| + */ |
| + OptionsPage.getVisibleOverlay_ = function() { |
| for (var name in this.registeredOverlayPages) { |
| - if (this.registeredOverlayPages[name].visible) |
| - return true; |
| + var page = this.registeredOverlayPages[name]; |
| + if (page.visible) |
| + return page; |
| } |
| - return false; |
| + return null; |
| }; |
| /** |
| @@ -159,7 +168,7 @@ cr.define('options', function() { |
| topPage = page; |
| } |
| return topPage; |
| - } |
| + }; |
| /** |
| * Closes the topmost open subpage, if any. |
| @@ -349,6 +358,9 @@ cr.define('options', function() { |
| // Install handler for key presses. |
| document.addEventListener('keydown', this.keyDownEventHandler_.bind(this)); |
| + |
| + document.addEventListener('focus', this.manageFocusChange_.bind(this), |
|
James Hawkins
2011/01/26 01:29:41
nit: All params on one line or lined up in one col
stuartmorgan
2011/01/26 17:27:03
The style guide explicitly allows either form.
James Hawkins
2011/01/26 18:08:25
Interesting. I had been told otherwise by a reputa
|
| + true); |
| }; |
| /** |
| @@ -373,6 +385,31 @@ cr.define('options', function() { |
| }; |
| /** |
| + * Called when focus changes; ensures that focus doesn't move outside |
| + * the topmost subpage/overlay. |
| + * @param {Event} e The focus change event. |
| + * @private |
| + */ |
| + OptionsPage.manageFocusChange_ = function(e) { |
| + var tabLoopRoot = null; |
|
James Hawkins
2011/01/26 01:29:41
This var name is a little confusing.
stuartmorgan
2011/01/26 17:27:03
Changed to focusableItemsRoot; hopefully that's a
|
| + // If an overlay is visible, that defines the tab loop |
|
James Hawkins
2011/01/26 01:29:41
nit: Period at end of sentence.
stuartmorgan
2011/01/26 17:27:03
Done.
|
| + var topPage = this.getVisibleOverlay_(); |
| + if (topPage) |
| + tabLoopRoot = topPage.pageDiv; |
| + // If a subpage is visible, use its parent as the tab loop constraint. |
| + // (The parent is used because it contains the close button.) |
| + if (!topPage) { |
| + var topPage = this.getTopmostVisiblePage(); |
| + if (topPage && topPage.nestingLevel > 0) |
| + tabLoopRoot = topPage.pageDiv.parentNode; |
| + } |
| + |
| + if (tabLoopRoot && !tabLoopRoot.contains(e.target)) { |
|
James Hawkins
2011/01/26 01:29:41
nit: No need for braces.
stuartmorgan
2011/01/26 17:27:03
Done.
|
| + topPage.focusFirstElement(); |
| + } |
| + }; |
| + |
| + /** |
| * A function to handle mouse events (mousedown or click) on the html body by |
| * closing subpages and/or stopping event propagation. |
| * @return {Event} a mousedown or click event. |
| @@ -542,6 +579,16 @@ cr.define('options', function() { |
| }, |
| /** |
| + * Focuses the first control on the page. |
| + */ |
| + focusFirstElement: function() { |
| + // Sets focus on the first interactive element in the page. |
| + focusElement = this.pageDiv.querySelector('button, input, list, select'); |
| + if (focusElement) |
| + focusElement.focus(); |
| + }, |
| + |
| + /** |
| * The nesting level of this page. |
| * @type {number} The nesting level of this page (0 for top-level page) |
| */ |