OLD | NEW |
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 /** | 5 /** |
6 * @fileoverview | 6 * @fileoverview |
7 * Functions related to controlling the modal UI state of the app. UI states | 7 * Functions related to controlling the modal UI state of the app. UI states |
8 * are expressed as HTML attributes with a dotted hierarchy. For example, the | 8 * are expressed as HTML attributes with a dotted hierarchy. For example, the |
9 * string 'host.shared' will match any elements with an associated attribute | 9 * string 'host.shared' will match any elements with an associated attribute |
10 * of 'host' or 'host.shared', showing those elements and hiding all others. | 10 * of 'host' or 'host.shared', showing those elements and hiding all others. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 * @return {void} Nothing. | 81 * @return {void} Nothing. |
82 */ | 82 */ |
83 remoting.updateModalUi = function(mode, attr) { | 83 remoting.updateModalUi = function(mode, attr) { |
84 var modes = mode.split('.'); | 84 var modes = mode.split('.'); |
85 for (var i = 1; i < modes.length; ++i) | 85 for (var i = 1; i < modes.length; ++i) |
86 modes[i] = modes[i - 1] + '.' + modes[i]; | 86 modes[i] = modes[i - 1] + '.' + modes[i]; |
87 var elements = document.querySelectorAll('[' + attr + ']'); | 87 var elements = document.querySelectorAll('[' + attr + ']'); |
88 // Hide elements first so that we don't end up trying to show two modal | 88 // Hide elements first so that we don't end up trying to show two modal |
89 // dialogs at once (which would break keyboard-navigation confinement). | 89 // dialogs at once (which would break keyboard-navigation confinement). |
90 for (var i = 0; i < elements.length; ++i) { | 90 for (var i = 0; i < elements.length; ++i) { |
91 var element = /** @type {Element} */ elements[i]; | 91 var element = /** @type {Element} */ (elements[i]); |
92 if (!remoting.hasModeAttribute(element, attr, modes)) { | 92 if (!remoting.hasModeAttribute(element, attr, modes)) { |
93 element.hidden = true; | 93 element.hidden = true; |
94 } | 94 } |
95 } | 95 } |
96 for (var i = 0; i < elements.length; ++i) { | 96 for (var i = 0; i < elements.length; ++i) { |
97 var element = /** @type {Element} */ elements[i]; | 97 var element = /** @type {Element} */ (elements[i]); |
98 if (remoting.hasModeAttribute(element, attr, modes)) { | 98 if (remoting.hasModeAttribute(element, attr, modes)) { |
99 element.hidden = false; | 99 element.hidden = false; |
100 var autofocusNode = element.querySelector('[autofocus]'); | 100 var autofocusNode = element.querySelector('[autofocus]'); |
101 if (autofocusNode) { | 101 if (autofocusNode) { |
102 autofocusNode.focus(); | 102 autofocusNode.focus(); |
103 } | 103 } |
104 } | 104 } |
105 } | 105 } |
106 }; | 106 }; |
107 | 107 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 */ | 155 */ |
156 remoting.getMajorMode = function() { | 156 remoting.getMajorMode = function() { |
157 return remoting.currentMode.split('.')[0]; | 157 return remoting.currentMode.split('.')[0]; |
158 }; | 158 }; |
159 | 159 |
160 /** | 160 /** |
161 * Helper function for showing or hiding the infographic UI based on | 161 * Helper function for showing or hiding the infographic UI based on |
162 * whether or not the user has already dismissed it. | 162 * whether or not the user has already dismissed it. |
163 * | 163 * |
164 * @param {string} mode | 164 * @param {string} mode |
165 * @param {!Object} items | 165 * @param {Object<?,string>} items |
166 */ | 166 */ |
167 remoting.showOrHideCallback = function(mode, items) { | 167 remoting.showOrHideCallback = function(mode, items) { |
168 // Get the first element of a dictionary or array, without needing to know | 168 // Get the first element of a dictionary or array, without needing to know |
169 // the key. | 169 // the key. |
| 170 var obj = /** @type {!Object} */(items); |
170 /** @type {string} */ | 171 /** @type {string} */ |
171 var key = Object.keys(items)[0]; | 172 var key = Object.keys(obj)[0]; |
172 var visited = !!items[key]; | 173 var visited = !!items[key]; |
173 document.getElementById(mode + '-first-run').hidden = visited; | 174 document.getElementById(mode + '-first-run').hidden = visited; |
174 document.getElementById(mode + '-content').hidden = !visited; | 175 document.getElementById(mode + '-content').hidden = !visited; |
175 }; | 176 }; |
176 | 177 |
| 178 /** |
| 179 * @param {Object<?,string>} items |
| 180 */ |
| 181 remoting.showOrHideCallbackIT2Me = function(items) { |
| 182 remoting.showOrHideCallback('it2me', items); |
| 183 } |
| 184 |
| 185 /** |
| 186 * @param {Object<?,string>} items |
| 187 */ |
| 188 remoting.showOrHideCallbackMe2Me = function(items) { |
| 189 remoting.showOrHideCallback('me2me', items); |
| 190 } |
| 191 |
177 remoting.showOrHideIT2MeUi = function() { | 192 remoting.showOrHideIT2MeUi = function() { |
178 chrome.storage.local.get(remoting.kIT2MeVisitedStorageKey, | 193 chrome.storage.local.get(remoting.kIT2MeVisitedStorageKey, |
179 remoting.showOrHideCallback.bind(null, 'it2me')); | 194 remoting.showOrHideCallbackIT2Me); |
180 }; | 195 }; |
181 | 196 |
182 remoting.showOrHideMe2MeUi = function() { | 197 remoting.showOrHideMe2MeUi = function() { |
183 chrome.storage.local.get(remoting.kMe2MeVisitedStorageKey, | 198 chrome.storage.local.get(remoting.kMe2MeVisitedStorageKey, |
184 remoting.showOrHideCallback.bind(null, 'me2me')); | 199 remoting.showOrHideCallbackMe2Me); |
185 }; | 200 }; |
186 | 201 |
187 remoting.showIT2MeUiAndSave = function() { | 202 remoting.showIT2MeUiAndSave = function() { |
188 var items = {}; | 203 var items = {}; |
189 items[remoting.kIT2MeVisitedStorageKey] = true; | 204 items[remoting.kIT2MeVisitedStorageKey] = true; |
190 chrome.storage.local.set(items); | 205 chrome.storage.local.set(items); |
191 remoting.showOrHideCallback('it2me', [true]); | 206 remoting.showOrHideCallback('it2me', [true]); |
192 }; | 207 }; |
193 | 208 |
194 remoting.showMe2MeUiAndSave = function() { | 209 remoting.showMe2MeUiAndSave = function() { |
(...skipping 12 matching lines...) Expand all Loading... |
207 | 222 |
208 | 223 |
209 /** | 224 /** |
210 * Initialize all modal dialogs (class kd-modaldialog), adding event handlers | 225 * Initialize all modal dialogs (class kd-modaldialog), adding event handlers |
211 * to confine keyboard navigation to child controls of the dialog when it is | 226 * to confine keyboard navigation to child controls of the dialog when it is |
212 * shown and restore keyboard navigation when it is hidden. | 227 * shown and restore keyboard navigation when it is hidden. |
213 */ | 228 */ |
214 remoting.initModalDialogs = function() { | 229 remoting.initModalDialogs = function() { |
215 var dialogs = document.querySelectorAll('.kd-modaldialog'); | 230 var dialogs = document.querySelectorAll('.kd-modaldialog'); |
216 var observer = new MutationObserver(confineOrRestoreFocus_); | 231 var observer = new MutationObserver(confineOrRestoreFocus_); |
217 var options = { | 232 var options = /** @type {MutationObserverInit} */({ |
218 subtree: false, | 233 subtree: false, |
219 attributes: true | 234 attributes: true |
220 }; | 235 }); |
221 for (var i = 0; i < dialogs.length; ++i) { | 236 for (var i = 0; i < dialogs.length; ++i) { |
222 observer.observe(dialogs[i], options); | 237 observer.observe(dialogs[i], options); |
223 } | 238 } |
224 }; | 239 }; |
225 | 240 |
226 /** | 241 /** |
227 * @param {Array.<MutationRecord>} mutations The set of mutations affecting | 242 * @param {Array.<MutationRecord>} mutations The set of mutations affecting |
228 * an observed node. | 243 * an observed node. |
229 */ | 244 */ |
230 function confineOrRestoreFocus_(mutations) { | 245 function confineOrRestoreFocus_(mutations) { |
231 // The list of mutations can include duplicates, so reduce it to a canonical | 246 // The list of mutations can include duplicates, so reduce it to a canonical |
232 // show/hide list. | 247 // show/hide list. |
233 /** @type {Array.<Element>} */ | 248 /** @type {Array.<Node>} */ |
234 var shown = []; | 249 var shown = []; |
235 /** @type {Array.<Element>} */ | 250 /** @type {Array.<Node>} */ |
236 var hidden = []; | 251 var hidden = []; |
237 for (var i = 0; i < mutations.length; ++i) { | 252 for (var i = 0; i < mutations.length; ++i) { |
238 var mutation = mutations[i]; | 253 var mutation = mutations[i]; |
239 if (mutation.type == 'attributes' && | 254 if (mutation.type == 'attributes' && |
240 mutation.attributeName == 'hidden') { | 255 mutation.attributeName == 'hidden') { |
241 var node = mutation.target; | 256 var node = mutation.target; |
242 if (node.hidden && hidden.indexOf(node) == -1) { | 257 if (node.hidden && hidden.indexOf(node) == -1) { |
243 hidden.push(node); | 258 hidden.push(node); |
244 } else if (!node.hidden && shown.indexOf(node) == -1) { | 259 } else if (!node.hidden && shown.indexOf(node) == -1) { |
245 shown.push(node); | 260 shown.push(node); |
246 } | 261 } |
247 } | 262 } |
248 } | 263 } |
249 var kSavedAttributeName = 'data-saved-tab-index'; | 264 var kSavedAttributeName = 'data-saved-tab-index'; |
250 // If any dialogs have been dismissed, restore all the tabIndex attributes. | 265 // If any dialogs have been dismissed, restore all the tabIndex attributes. |
251 if (hidden.length != 0) { | 266 if (hidden.length != 0) { |
252 var elements = document.querySelectorAll('[' + kSavedAttributeName + ']'); | 267 var elements = document.querySelectorAll('[' + kSavedAttributeName + ']'); |
253 for (var i = 0 ; i < elements.length; ++i) { | 268 for (var i = 0 ; i < elements.length; ++i) { |
254 var element = /** @type {Element} */ elements[i]; | 269 var element = /** @type {Element} */ (elements[i]); |
255 element.tabIndex = element.getAttribute(kSavedAttributeName); | 270 element.tabIndex = element.getAttribute(kSavedAttributeName); |
256 element.removeAttribute(kSavedAttributeName); | 271 element.removeAttribute(kSavedAttributeName); |
257 } | 272 } |
258 } | 273 } |
259 // If any dialogs have been shown, confine keyboard navigation to the first | 274 // If any dialogs have been shown, confine keyboard navigation to the first |
260 // one. We don't have nested modal dialogs, so this will suffice for now. | 275 // one. We don't have nested modal dialogs, so this will suffice for now. |
261 if (shown.length != 0) { | 276 if (shown.length != 0) { |
262 var selector = '[tabIndex],a,area,button,input,select,textarea'; | 277 var selector = '[tabIndex],a,area,button,input,select,textarea'; |
263 var disable = document.querySelectorAll(selector); | 278 var disable = document.querySelectorAll(selector); |
264 var except = shown[0].querySelectorAll(selector); | 279 var except = shown[0].querySelectorAll(selector); |
265 for (var i = 0; i < disable.length; ++i) { | 280 for (var i = 0; i < disable.length; ++i) { |
266 var element = /** @type {Element} */ disable[i]; | 281 var element = /** @type {Element} */ (disable[i]); |
267 var removeFromKeyboardNavigation = true; | 282 var removeFromKeyboardNavigation = true; |
268 for (var j = 0; j < except.length; ++j) { // No indexOf on NodeList | 283 for (var j = 0; j < except.length; ++j) { // No indexOf on NodeList |
269 if (element == except[j]) { | 284 if (element == except[j]) { |
270 removeFromKeyboardNavigation = false; | 285 removeFromKeyboardNavigation = false; |
271 break; | 286 break; |
272 } | 287 } |
273 } | 288 } |
274 if (removeFromKeyboardNavigation) { | 289 if (removeFromKeyboardNavigation) { |
275 element.setAttribute(kSavedAttributeName, element.tabIndex); | 290 element.setAttribute(kSavedAttributeName, element.tabIndex); |
276 element.tabIndex = -1; | 291 element.tabIndex = -1; |
277 } | 292 } |
278 } | 293 } |
279 } | 294 } |
280 } | 295 } |
281 | 296 |
282 /** | 297 /** |
283 * @param {string} tag | 298 * @param {string} tag |
284 */ | 299 */ |
285 remoting.showSetupProcessingMessage = function(tag) { | 300 remoting.showSetupProcessingMessage = function(tag) { |
286 var messageDiv = document.getElementById('host-setup-processing-message'); | 301 var messageDiv = document.getElementById('host-setup-processing-message'); |
287 l10n.localizeElementFromTag(messageDiv, tag); | 302 l10n.localizeElementFromTag(messageDiv, tag); |
288 remoting.setMode(remoting.AppMode.HOST_SETUP_PROCESSING); | 303 remoting.setMode(remoting.AppMode.HOST_SETUP_PROCESSING); |
289 } | 304 } |
OLD | NEW |