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..c618238ae46d28028b4199f8d944cc1abc7ab29b 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), |
| + true); |
| }; |
| /** |
| @@ -373,6 +385,30 @@ 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 focusableItemsRoot = null; |
|
arv (Not doing code reviews)
2011/01/26 17:55:49
no need to assign null here.
stuartmorgan
2011/01/26 18:19:08
Done.
|
| + // If an overlay is visible, that defines the tab loop. |
| + var topPage = this.getVisibleOverlay_(); |
| + if (topPage) |
| + focusableItemsRoot = 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) |
| + focusableItemsRoot = topPage.pageDiv.parentNode; |
| + } |
| + |
| + if (focusableItemsRoot && !focusableItemsRoot.contains(e.target)) |
| + 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 +578,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'); |
|
arv (Not doing code reviews)
2011/01/26 17:55:49
missing var
stuartmorgan
2011/01/26 18:19:08
Done.
|
| + if (focusElement) |
| + focusElement.focus(); |
| + }, |
| + |
| + /** |
| * The nesting level of this page. |
| * @type {number} The nesting level of this page (0 for top-level page) |
| */ |