Chromium Code Reviews| 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); |
|
garykac
2015/01/12 20:22:37
It had trouble with the bind, so this removes the
| |
| 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 |