Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: chrome/browser/resources/shared/js/cr/ui/focus_manager.js

Issue 10907148: Implement popup bubbles for the controlled setting indicator (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comment addressed. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 cr.define('cr.ui', function() { 5 cr.define('cr.ui', function() {
6 /** 6 /**
7 * Constructor for FocusManager singleton. Checks focus of elements to ensure 7 * Constructor for FocusManager singleton. Checks focus of elements to ensure
8 * that elements in "background" pages (i.e., those in a dialog that is not 8 * that elements in "background" pages (i.e., those in a dialog that is not
9 * the topmost overlay) do not receive focus. 9 * the topmost overlay) do not receive focus.
10 * @constructor 10 * @constructor
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 * @return {Array.Element} The focusable elements. 59 * @return {Array.Element} The focusable elements.
60 */ 60 */
61 getFocusableElements_: function() { 61 getFocusableElements_: function() {
62 var focusableDiv = this.getFocusParent(); 62 var focusableDiv = this.getFocusParent();
63 63
64 // Create a TreeWalker object to traverse the DOM from |focusableDiv|. 64 // Create a TreeWalker object to traverse the DOM from |focusableDiv|.
65 var treeWalker = document.createTreeWalker( 65 var treeWalker = document.createTreeWalker(
66 focusableDiv, 66 focusableDiv,
67 NodeFilter.SHOW_ELEMENT, 67 NodeFilter.SHOW_ELEMENT,
68 { acceptNode: function(node) { 68 { acceptNode: function(node) {
69 var style = window.getComputedStyle(node);
69 // Reject all hidden nodes. FILTER_REJECT also rejects these 70 // Reject all hidden nodes. FILTER_REJECT also rejects these
70 // nodes' children, so non-hidden elements that are descendants of 71 // nodes' children, so non-hidden elements that are descendants of
71 // hidden <div>s will correctly be rejected. 72 // hidden <div>s will correctly be rejected.
72 if (node.hidden) 73 if (node.hidden || style.display == 'none' ||
74 style.visibility == 'hidden')
Evan Stade 2012/09/21 12:12:11 curlies
bartfab (slow) 2012/09/24 17:15:55 Done.
73 return NodeFilter.FILTER_REJECT; 75 return NodeFilter.FILTER_REJECT;
74 76
75 // Skip nodes that cannot receive focus. FILTER_SKIP does not 77 // Skip nodes that cannot receive focus. FILTER_SKIP does not
76 // cause this node's children also to be skipped. 78 // cause this node's children also to be skipped.
77 if (node.disabled || node.tabIndex < 0) 79 if (node.disabled || node.tabIndex < 0)
78 return NodeFilter.FILTER_SKIP; 80 return NodeFilter.FILTER_SKIP;
79 81
80 // Accept nodes that are non-hidden and focusable. 82 // Accept nodes that are non-hidden and focusable.
81 return NodeFilter.FILTER_ACCEPT; 83 return NodeFilter.FILTER_ACCEPT;
82 } 84 }
83 }, 85 },
84 false); 86 false);
85 87
86 var focusable = []; 88 var focusable = [];
87 while (treeWalker.nextNode()) 89 while (treeWalker.nextNode())
88 focusable.push(treeWalker.currentNode); 90 focusable.push(treeWalker.currentNode);
89 91
90 return focusable; 92 return focusable;
91 }, 93 },
92 94
93 /** 95 /**
94 * Retrieves the page's focusable elements and, if there are any, focuses 96 * Dispatches an 'elementFocused' event to notify an element that it has
95 * the first one. 97 * received focus. When focus wraps around within the a page, only the
98 * element that has focus after the wrapping receives an 'elementFocused'
99 * event. This differs from the native 'focus' event which is received by
100 * an element outside the page first, followed by a 'focus' on an element
101 * within the page after the FocusManager has intervened.
102 * @param {Element} element The element that has received focus.
96 * @private 103 * @private
97 */ 104 */
98 focusFirstElement_: function() { 105 dispatchFocusEvent_: function(element) {
99 var focusableElements = this.getFocusableElements_(); 106 cr.dispatchSimpleEvent(element, 'elementFocused', true, false);
100 if (focusableElements.length != 0)
101 focusableElements[0].focus();
102 }, 107 },
103 108
104 /** 109 /**
105 * Retrieves the page's focusable elements and, if there are any, focuses
106 * the last one.
107 * @private
108 */
109 focusLastElement_: function() {
110 var focusableElements = this.getFocusableElements_();
111 if (focusableElements.length != 0)
112 focusableElements[focusableElements.length - 1].focus();
113 },
114
115 /**
116 * Attempts to focus the appropriate element in the current dialog. 110 * Attempts to focus the appropriate element in the current dialog.
117 * @private 111 * @private
118 */ 112 */
119 setFocus_: function() { 113 setFocus_: function() {
120 // If |this.focusDirBackwards_| is true, the user has pressed "Shift+Tab" 114 // If |this.focusDirBackwards_| is true, the user has pressed "Shift+Tab"
121 // and has caused the focus to be transferred backward, outside of the 115 // and has caused the focus to be transferred backward, outside of the
122 // current dialog. In this case, loop around and try to focus the last 116 // current dialog. In this case, loop around and try to focus the last
123 // element of the dialog; otherwise, try to focus the first element of the 117 // element of the dialog; otherwise, try to focus the first element of the
124 // dialog. 118 // dialog.
125 if (this.focusDirBackwards_) 119 var focusableElements = this.getFocusableElements_();
126 this.focusLastElement_(); 120 var element = this.focusDirBackwards_ ? focusableElements.pop() :
127 else 121 focusableElements.shift();
128 this.focusFirstElement_(); 122 if (element) {
123 element.focus();
124 this.dispatchFocusEvent_(element);
125 }
129 }, 126 },
130 127
131 /** 128 /**
132 * Attempts to focus the first element in the current dialog. 129 * Attempts to focus the first element in the current dialog.
133 */ 130 */
134 focusFirstElement: function() { 131 focusFirstElement: function() {
135 this.focusFirstElement_(); 132 this.focusFirstElement_();
136 }, 133 },
137 134
138 /** 135 /**
139 * Handler for focus events on the page. 136 * Handler for focus events on the page.
140 * @param {Event} event The focus event. 137 * @param {Event} event The focus event.
141 * @private 138 * @private
142 */ 139 */
143 onDocumentFocus_: function(event) { 140 onDocumentFocus_: function(event) {
144 // If the element being focused is a descendant of the currently visible 141 // If the element being focused is a descendant of the currently visible
145 // page, focus is valid. 142 // page, focus is valid.
146 if (this.isDescendantOf_(this.getFocusParent(), event.target)) 143 if (this.isDescendantOf_(this.getFocusParent(), event.target)) {
144 this.dispatchFocusEvent_(event.target);
147 return; 145 return;
146 }
148 147
149 // The target of the focus event is not in the topmost visible page and 148 // The target of the focus event is not in the topmost visible page and
150 // should not be focused. 149 // should not be focused.
151 event.target.blur(); 150 event.target.blur();
152 151
152 // Attempt to wrap around focus within the current page.
153 this.setFocus_(); 153 this.setFocus_();
154 }, 154 },
155 155
156 /** 156 /**
157 * Handler for keydown events on the page. 157 * Handler for keydown events on the page.
158 * @param {Event} event The keydown event. 158 * @param {Event} event The keydown event.
159 * @private 159 * @private
160 */ 160 */
161 onDocumentKeyDown_: function(event) { 161 onDocumentKeyDown_: function(event) {
162 /** @const */ var tabKeyCode = 9; 162 /** @const */ var tabKeyCode = 9;
(...skipping 13 matching lines...) Expand all
176 true); 176 true);
177 document.addEventListener('keydown', this.onDocumentKeyDown_.bind(this), 177 document.addEventListener('keydown', this.onDocumentKeyDown_.bind(this),
178 true); 178 true);
179 }, 179 },
180 }; 180 };
181 181
182 return { 182 return {
183 FocusManager: FocusManager, 183 FocusManager: FocusManager,
184 }; 184 };
185 }); 185 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698