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

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: All comments 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') {
73 return NodeFilter.FILTER_REJECT; 75 return NodeFilter.FILTER_REJECT;
76 }
74 77
75 // Skip nodes that cannot receive focus. FILTER_SKIP does not 78 // Skip nodes that cannot receive focus. FILTER_SKIP does not
76 // cause this node's children also to be skipped. 79 // cause this node's children also to be skipped.
77 if (node.disabled || node.tabIndex < 0) 80 if (node.disabled || node.tabIndex < 0)
78 return NodeFilter.FILTER_SKIP; 81 return NodeFilter.FILTER_SKIP;
79 82
80 // Accept nodes that are non-hidden and focusable. 83 // Accept nodes that are non-hidden and focusable.
81 return NodeFilter.FILTER_ACCEPT; 84 return NodeFilter.FILTER_ACCEPT;
82 } 85 }
83 }, 86 },
84 false); 87 false);
85 88
86 var focusable = []; 89 var focusable = [];
87 while (treeWalker.nextNode()) 90 while (treeWalker.nextNode())
88 focusable.push(treeWalker.currentNode); 91 focusable.push(treeWalker.currentNode);
89 92
90 return focusable; 93 return focusable;
91 }, 94 },
92 95
93 /** 96 /**
94 * Retrieves the page's focusable elements and, if there are any, focuses 97 * Dispatches an 'elementFocused' event to notify an element that it has
95 * the first one. 98 * received focus. When focus wraps around within the a page, only the
99 * element that has focus after the wrapping receives an 'elementFocused'
100 * event. This differs from the native 'focus' event which is received by
101 * an element outside the page first, followed by a 'focus' on an element
102 * within the page after the FocusManager has intervened.
103 * @param {Element} element The element that has received focus.
96 * @private 104 * @private
97 */ 105 */
98 focusFirstElement_: function() { 106 dispatchFocusEvent_: function(element) {
99 var focusableElements = this.getFocusableElements_(); 107 cr.dispatchSimpleEvent(element, 'elementFocused', true, false);
100 if (focusableElements.length != 0)
101 focusableElements[0].focus();
102 }, 108 },
103 109
104 /** 110 /**
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. 111 * Attempts to focus the appropriate element in the current dialog.
117 * @private 112 * @private
118 */ 113 */
119 setFocus_: function() { 114 setFocus_: function() {
120 // If |this.focusDirBackwards_| is true, the user has pressed "Shift+Tab" 115 // If |this.focusDirBackwards_| is true, the user has pressed "Shift+Tab"
121 // and has caused the focus to be transferred backward, outside of the 116 // 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 117 // 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 118 // element of the dialog; otherwise, try to focus the first element of the
124 // dialog. 119 // dialog.
125 if (this.focusDirBackwards_) 120 var focusableElements = this.getFocusableElements_();
126 this.focusLastElement_(); 121 var element = this.focusDirBackwards_ ? focusableElements.pop() :
127 else 122 focusableElements.shift();
128 this.focusFirstElement_(); 123 if (element) {
124 element.focus();
125 this.dispatchFocusEvent_(element);
126 }
129 }, 127 },
130 128
131 /** 129 /**
132 * Attempts to focus the first element in the current dialog. 130 * Attempts to focus the first element in the current dialog.
133 */ 131 */
134 focusFirstElement: function() { 132 focusFirstElement: function() {
135 this.focusFirstElement_(); 133 this.focusFirstElement_();
136 }, 134 },
137 135
138 /** 136 /**
139 * Handler for focus events on the page. 137 * Handler for focus events on the page.
140 * @param {Event} event The focus event. 138 * @param {Event} event The focus event.
141 * @private 139 * @private
142 */ 140 */
143 onDocumentFocus_: function(event) { 141 onDocumentFocus_: function(event) {
144 // If the element being focused is a descendant of the currently visible 142 // If the element being focused is a descendant of the currently visible
145 // page, focus is valid. 143 // page, focus is valid.
146 if (this.isDescendantOf_(this.getFocusParent(), event.target)) 144 if (this.isDescendantOf_(this.getFocusParent(), event.target)) {
145 this.dispatchFocusEvent_(event.target);
147 return; 146 return;
147 }
148 148
149 // The target of the focus event is not in the topmost visible page and 149 // The target of the focus event is not in the topmost visible page and
150 // should not be focused. 150 // should not be focused.
151 event.target.blur(); 151 event.target.blur();
152 152
153 // Attempt to wrap around focus within the current page.
153 this.setFocus_(); 154 this.setFocus_();
154 }, 155 },
155 156
156 /** 157 /**
157 * Handler for keydown events on the page. 158 * Handler for keydown events on the page.
158 * @param {Event} event The keydown event. 159 * @param {Event} event The keydown event.
159 * @private 160 * @private
160 */ 161 */
161 onDocumentKeyDown_: function(event) { 162 onDocumentKeyDown_: function(event) {
162 /** @const */ var tabKeyCode = 9; 163 /** @const */ var tabKeyCode = 9;
(...skipping 13 matching lines...) Expand all
176 true); 177 true);
177 document.addEventListener('keydown', this.onDocumentKeyDown_.bind(this), 178 document.addEventListener('keydown', this.onDocumentKeyDown_.bind(this),
178 true); 179 true);
179 }, 180 },
180 }; 181 };
181 182
182 return { 183 return {
183 FocusManager: FocusManager, 184 FocusManager: FocusManager,
184 }; 185 };
185 }); 186 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/shared/js/cr/ui/bubble.js ('k') | chrome/browser/resources/shared_resources.grd » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698