| 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 // <include src="shortcut_util.js"> | 5 // <include src="shortcut_util.js"> |
| 6 | 6 |
| 7 cr.define('extensions', function() { | 7 cr.define('extensions', function() { |
| 8 'use strict'; | 8 'use strict'; |
| 9 | 9 |
| 10 /** | 10 /** |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 * metadata given in |extension|. | 66 * metadata given in |extension|. |
| 67 * @param {chrome.developerPrivate.ExtensionInfo} extension A dictionary of | 67 * @param {chrome.developerPrivate.ExtensionInfo} extension A dictionary of |
| 68 * extension metadata. | 68 * extension metadata. |
| 69 * @private | 69 * @private |
| 70 */ | 70 */ |
| 71 createNodeForExtension_: function(extension) { | 71 createNodeForExtension_: function(extension) { |
| 72 if (extension.commands.length == 0 || | 72 if (extension.commands.length == 0 || |
| 73 extension.state == chrome.developerPrivate.ExtensionState.DISABLED) | 73 extension.state == chrome.developerPrivate.ExtensionState.DISABLED) |
| 74 return; | 74 return; |
| 75 | 75 |
| 76 var template = $('template-collection-extension-commands').querySelector( | 76 var template = |
| 77 '.extension-command-list-extension-item-wrapper'); | 77 $('template-collection-extension-commands') |
| 78 .querySelector('.extension-command-list-extension-item-wrapper'); |
| 78 var node = template.cloneNode(true); | 79 var node = template.cloneNode(true); |
| 79 | 80 |
| 80 var title = node.querySelector('.extension-title'); | 81 var title = node.querySelector('.extension-title'); |
| 81 title.textContent = extension.name; | 82 title.textContent = extension.name; |
| 82 | 83 |
| 83 this.appendChild(node); | 84 this.appendChild(node); |
| 84 | 85 |
| 85 // Iterate over the commands data within the extension and add each item | 86 // Iterate over the commands data within the extension and add each item |
| 86 // to the list. | 87 // to the list. |
| 87 extension.commands.forEach( | 88 extension.commands.forEach( |
| 88 this.createNodeForCommand_.bind(this, extension.id)); | 89 this.createNodeForCommand_.bind(this, extension.id)); |
| 89 }, | 90 }, |
| 90 | 91 |
| 91 /** | 92 /** |
| 92 * Synthesizes and initializes an HTML element for the extension command | 93 * Synthesizes and initializes an HTML element for the extension command |
| 93 * metadata given in |command|. | 94 * metadata given in |command|. |
| 94 * @param {string} extensionId The associated extension's id. | 95 * @param {string} extensionId The associated extension's id. |
| 95 * @param {chrome.developerPrivate.Command} command A dictionary of | 96 * @param {chrome.developerPrivate.Command} command A dictionary of |
| 96 * extension command metadata. | 97 * extension command metadata. |
| 97 * @private | 98 * @private |
| 98 */ | 99 */ |
| 99 createNodeForCommand_: function(extensionId, command) { | 100 createNodeForCommand_: function(extensionId, command) { |
| 100 var template = $('template-collection-extension-commands').querySelector( | 101 var template = |
| 101 '.extension-command-list-command-item-wrapper'); | 102 $('template-collection-extension-commands') |
| 103 .querySelector('.extension-command-list-command-item-wrapper'); |
| 102 var node = template.cloneNode(true); | 104 var node = template.cloneNode(true); |
| 103 node.id = this.createElementId_('command', extensionId, command.name); | 105 node.id = this.createElementId_('command', extensionId, command.name); |
| 104 | 106 |
| 105 var description = node.querySelector('.command-description'); | 107 var description = node.querySelector('.command-description'); |
| 106 description.textContent = command.description; | 108 description.textContent = command.description; |
| 107 | 109 |
| 108 var shortcutNode = node.querySelector('.command-shortcut-text'); | 110 var shortcutNode = node.querySelector('.command-shortcut-text'); |
| 109 shortcutNode.addEventListener('mouseup', | 111 shortcutNode.addEventListener('mouseup', this.startCapture_.bind(this)); |
| 110 this.startCapture_.bind(this)); | |
| 111 shortcutNode.addEventListener('focus', this.handleFocus_.bind(this)); | 112 shortcutNode.addEventListener('focus', this.handleFocus_.bind(this)); |
| 112 shortcutNode.addEventListener('blur', this.handleBlur_.bind(this)); | 113 shortcutNode.addEventListener('blur', this.handleBlur_.bind(this)); |
| 113 shortcutNode.addEventListener('keydown', this.handleKeyDown_.bind(this)); | 114 shortcutNode.addEventListener('keydown', this.handleKeyDown_.bind(this)); |
| 114 shortcutNode.addEventListener('keyup', this.handleKeyUp_.bind(this)); | 115 shortcutNode.addEventListener('keyup', this.handleKeyUp_.bind(this)); |
| 115 if (!command.isActive) { | 116 if (!command.isActive) { |
| 116 shortcutNode.textContent = | 117 shortcutNode.textContent = |
| 117 loadTimeData.getString('extensionCommandsInactive'); | 118 loadTimeData.getString('extensionCommandsInactive'); |
| 118 | 119 |
| 119 var commandShortcut = node.querySelector('.command-shortcut'); | 120 var commandShortcut = node.querySelector('.command-shortcut'); |
| 120 commandShortcut.classList.add('inactive-keybinding'); | 121 commandShortcut.classList.add('inactive-keybinding'); |
| 121 } else { | 122 } else { |
| 122 shortcutNode.textContent = command.keybinding; | 123 shortcutNode.textContent = command.keybinding; |
| 123 } | 124 } |
| 124 | 125 |
| 125 var commandClear = node.querySelector('.command-clear'); | 126 var commandClear = node.querySelector('.command-clear'); |
| 126 commandClear.id = this.createElementId_( | 127 commandClear.id = |
| 127 'clear', extensionId, command.name); | 128 this.createElementId_('clear', extensionId, command.name); |
| 128 commandClear.title = loadTimeData.getString('extensionCommandsDelete'); | 129 commandClear.title = loadTimeData.getString('extensionCommandsDelete'); |
| 129 commandClear.addEventListener('click', this.handleClear_.bind(this)); | 130 commandClear.addEventListener('click', this.handleClear_.bind(this)); |
| 130 | 131 |
| 131 var select = node.querySelector('.command-scope'); | 132 var select = node.querySelector('.command-scope'); |
| 132 select.id = this.createElementId_( | 133 select.id = |
| 133 'setCommandScope', extensionId, command.name); | 134 this.createElementId_('setCommandScope', extensionId, command.name); |
| 134 select.hidden = false; | 135 select.hidden = false; |
| 135 // Add the 'In Chrome' option. | 136 // Add the 'In Chrome' option. |
| 136 var option = document.createElement('option'); | 137 var option = document.createElement('option'); |
| 137 option.textContent = loadTimeData.getString('extensionCommandsRegular'); | 138 option.textContent = loadTimeData.getString('extensionCommandsRegular'); |
| 138 select.appendChild(option); | 139 select.appendChild(option); |
| 139 if (command.isExtensionAction || !command.isActive) { | 140 if (command.isExtensionAction || !command.isActive) { |
| 140 // Extension actions cannot be global, so we might as well disable the | 141 // Extension actions cannot be global, so we might as well disable the |
| 141 // combo box, to signify that, and if the command is inactive, it | 142 // combo box, to signify that, and if the command is inactive, it |
| 142 // doesn't make sense to allow the user to adjust the scope. | 143 // doesn't make sense to allow the user to adjust the scope. |
| 143 select.disabled = true; | 144 select.disabled = true; |
| 144 } else { | 145 } else { |
| 145 // Add the 'Global' option. | 146 // Add the 'Global' option. |
| 146 option = document.createElement('option'); | 147 option = document.createElement('option'); |
| 147 option.textContent = loadTimeData.getString('extensionCommandsGlobal'); | 148 option.textContent = loadTimeData.getString('extensionCommandsGlobal'); |
| 148 select.appendChild(option); | 149 select.appendChild(option); |
| 149 select.selectedIndex = | 150 select.selectedIndex = |
| 150 command.scope == chrome.developerPrivate.CommandScope.GLOBAL ? | 151 command.scope == chrome.developerPrivate.CommandScope.GLOBAL ? 1 : |
| 151 1 : 0; | 152 0; |
| 152 | 153 |
| 153 select.addEventListener( | 154 select.addEventListener( |
| 154 'change', this.handleSetCommandScope_.bind(this)); | 155 'change', this.handleSetCommandScope_.bind(this)); |
| 155 } | 156 } |
| 156 | 157 |
| 157 this.appendChild(node); | 158 this.appendChild(node); |
| 158 }, | 159 }, |
| 159 | 160 |
| 160 /** | 161 /** |
| 161 * Starts keystroke capture to determine which key to use for a particular | 162 * Starts keystroke capture to determine which key to use for a particular |
| (...skipping 10 matching lines...) Expand all Loading... |
| 172 var shortcutNode = event.target; | 173 var shortcutNode = event.target; |
| 173 this.oldValue_ = shortcutNode.textContent; | 174 this.oldValue_ = shortcutNode.textContent; |
| 174 shortcutNode.textContent = | 175 shortcutNode.textContent = |
| 175 loadTimeData.getString('extensionCommandsStartTyping'); | 176 loadTimeData.getString('extensionCommandsStartTyping'); |
| 176 shortcutNode.parentElement.classList.add('capturing'); | 177 shortcutNode.parentElement.classList.add('capturing'); |
| 177 | 178 |
| 178 var commandClear = | 179 var commandClear = |
| 179 shortcutNode.parentElement.querySelector('.command-clear'); | 180 shortcutNode.parentElement.querySelector('.command-clear'); |
| 180 commandClear.hidden = true; | 181 commandClear.hidden = true; |
| 181 | 182 |
| 182 this.capturingElement_ = /** @type {HTMLElement} */(event.target); | 183 this.capturingElement_ = /** @type {HTMLElement} */ (event.target); |
| 183 }, | 184 }, |
| 184 | 185 |
| 185 /** | 186 /** |
| 186 * Ends keystroke capture and either restores the old value or (if valid | 187 * Ends keystroke capture and either restores the old value or (if valid |
| 187 * value) sets the new value as active.. | 188 * value) sets the new value as active.. |
| 188 * @param {Event} event The keyboard event to consider. | 189 * @param {Event} event The keyboard event to consider. |
| 189 * @private | 190 * @private |
| 190 */ | 191 */ |
| 191 endCapture_: function(event) { | 192 endCapture_: function(event) { |
| 192 if (!this.capturingElement_) | 193 if (!this.capturingElement_) |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 var commandShortcut = event.target.parentElement; | 246 var commandShortcut = event.target.parentElement; |
| 246 commandShortcut.classList.remove('focused'); | 247 commandShortcut.classList.remove('focused'); |
| 247 }, | 248 }, |
| 248 | 249 |
| 249 /** | 250 /** |
| 250 * The KeyDown handler. | 251 * The KeyDown handler. |
| 251 * @param {Event} event The keyboard event to consider. | 252 * @param {Event} event The keyboard event to consider. |
| 252 * @private | 253 * @private |
| 253 */ | 254 */ |
| 254 handleKeyDown_: function(event) { | 255 handleKeyDown_: function(event) { |
| 255 event = /** @type {KeyboardEvent} */(event); | 256 event = /** @type {KeyboardEvent} */ (event); |
| 256 if (event.keyCode == extensions.Key.Escape) { | 257 if (event.keyCode == extensions.Key.Escape) { |
| 257 if (!this.capturingElement_) { | 258 if (!this.capturingElement_) { |
| 258 // If we're not currently capturing, allow escape to propagate (so it | 259 // If we're not currently capturing, allow escape to propagate (so it |
| 259 // can close the overflow). | 260 // can close the overflow). |
| 260 return; | 261 return; |
| 261 } | 262 } |
| 262 // Otherwise, escape cancels capturing. | 263 // Otherwise, escape cancels capturing. |
| 263 this.endCapture_(event); | 264 this.endCapture_(event); |
| 264 var parsed = this.parseElementId_('clear', | 265 var parsed = this.parseElementId_( |
| 266 'clear', |
| 265 event.target.parentElement.querySelector('.command-clear').id); | 267 event.target.parentElement.querySelector('.command-clear').id); |
| 266 chrome.developerPrivate.updateExtensionCommand({ | 268 chrome.developerPrivate.updateExtensionCommand({ |
| 267 extensionId: parsed.extensionId, | 269 extensionId: parsed.extensionId, |
| 268 commandName: parsed.commandName, | 270 commandName: parsed.commandName, |
| 269 keybinding: '' | 271 keybinding: '' |
| 270 }); | 272 }); |
| 271 event.preventDefault(); | 273 event.preventDefault(); |
| 272 event.stopPropagation(); | 274 event.stopPropagation(); |
| 273 return; | 275 return; |
| 274 } | 276 } |
| 275 if (event.keyCode == extensions.Key.Tab) { | 277 if (event.keyCode == extensions.Key.Tab) { |
| 276 // Allow tab propagation for keyboard navigation. | 278 // Allow tab propagation for keyboard navigation. |
| 277 return; | 279 return; |
| 278 } | 280 } |
| 279 | 281 |
| 280 if (!this.capturingElement_) | 282 if (!this.capturingElement_) |
| 281 this.startCapture_(event); | 283 this.startCapture_(event); |
| 282 | 284 |
| 283 this.handleKey_(event); | 285 this.handleKey_(event); |
| 284 }, | 286 }, |
| 285 | 287 |
| 286 /** | 288 /** |
| 287 * The KeyUp handler. | 289 * The KeyUp handler. |
| 288 * @param {Event} event The keyboard event to consider. | 290 * @param {Event} event The keyboard event to consider. |
| 289 * @private | 291 * @private |
| 290 */ | 292 */ |
| 291 handleKeyUp_: function(event) { | 293 handleKeyUp_: function(event) { |
| 292 event = /** @type {KeyboardEvent} */(event); | 294 event = /** @type {KeyboardEvent} */ (event); |
| 293 if (event.keyCode == extensions.Key.Tab || | 295 if (event.keyCode == extensions.Key.Tab || |
| 294 event.keyCode == extensions.Key.Escape) { | 296 event.keyCode == extensions.Key.Escape) { |
| 295 // We need to allow tab propagation for keyboard navigation, and escapes | 297 // We need to allow tab propagation for keyboard navigation, and escapes |
| 296 // are fully handled in handleKeyDown. | 298 // are fully handled in handleKeyDown. |
| 297 return; | 299 return; |
| 298 } | 300 } |
| 299 | 301 |
| 300 // We want to make it easy to change from Ctrl+Shift+ to just Ctrl+ by | 302 // We want to make it easy to change from Ctrl+Shift+ to just Ctrl+ by |
| 301 // releasing Shift, but we also don't want it to be easy to lose for | 303 // releasing Shift, but we also don't want it to be easy to lose for |
| 302 // example Ctrl+Shift+F to Ctrl+ just because you didn't release Ctrl | 304 // example Ctrl+Shift+F to Ctrl+ just because you didn't release Ctrl |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 var node = event.target; | 346 var node = event.target; |
| 345 while (node && !node.id) | 347 while (node && !node.id) |
| 346 node = node.parentElement; | 348 node = node.parentElement; |
| 347 | 349 |
| 348 this.oldValue_ = keystroke; // Forget what the old value was. | 350 this.oldValue_ = keystroke; // Forget what the old value was. |
| 349 var parsed = this.parseElementId_('command', node.id); | 351 var parsed = this.parseElementId_('command', node.id); |
| 350 | 352 |
| 351 // Ending the capture must occur before calling | 353 // Ending the capture must occur before calling |
| 352 // setExtensionCommandShortcut to ensure the shortcut is set. | 354 // setExtensionCommandShortcut to ensure the shortcut is set. |
| 353 this.endCapture_(event); | 355 this.endCapture_(event); |
| 354 chrome.developerPrivate.updateExtensionCommand( | 356 chrome.developerPrivate.updateExtensionCommand({ |
| 355 {extensionId: parsed.extensionId, | 357 extensionId: parsed.extensionId, |
| 356 commandName: parsed.commandName, | 358 commandName: parsed.commandName, |
| 357 keybinding: keystroke}); | 359 keybinding: keystroke |
| 360 }); |
| 358 } | 361 } |
| 359 }, | 362 }, |
| 360 | 363 |
| 361 /** | 364 /** |
| 362 * A handler for the delete command button. | 365 * A handler for the delete command button. |
| 363 * @param {Event} event The mouse event to consider. | 366 * @param {Event} event The mouse event to consider. |
| 364 * @private | 367 * @private |
| 365 */ | 368 */ |
| 366 handleClear_: function(event) { | 369 handleClear_: function(event) { |
| 367 var parsed = this.parseElementId_('clear', event.target.id); | 370 var parsed = this.parseElementId_('clear', event.target.id); |
| 368 chrome.developerPrivate.updateExtensionCommand( | 371 chrome.developerPrivate.updateExtensionCommand({ |
| 369 {extensionId: parsed.extensionId, | 372 extensionId: parsed.extensionId, |
| 370 commandName: parsed.commandName, | 373 commandName: parsed.commandName, |
| 371 keybinding: ''}); | 374 keybinding: '' |
| 375 }); |
| 372 }, | 376 }, |
| 373 | 377 |
| 374 /** | 378 /** |
| 375 * A handler for the setting the scope of the command. | 379 * A handler for the setting the scope of the command. |
| 376 * @param {Event} event The mouse event to consider. | 380 * @param {Event} event The mouse event to consider. |
| 377 * @private | 381 * @private |
| 378 */ | 382 */ |
| 379 handleSetCommandScope_: function(event) { | 383 handleSetCommandScope_: function(event) { |
| 380 var parsed = this.parseElementId_('setCommandScope', event.target.id); | 384 var parsed = this.parseElementId_('setCommandScope', event.target.id); |
| 381 var element = document.getElementById( | 385 var element = document.getElementById( |
| 382 'setCommandScope-' + parsed.extensionId + '-' + parsed.commandName); | 386 'setCommandScope-' + parsed.extensionId + '-' + parsed.commandName); |
| 383 var scope = element.selectedIndex == 1 ? | 387 var scope = element.selectedIndex == 1 ? |
| 384 chrome.developerPrivate.CommandScope.GLOBAL : | 388 chrome.developerPrivate.CommandScope.GLOBAL : |
| 385 chrome.developerPrivate.CommandScope.CHROME; | 389 chrome.developerPrivate.CommandScope.CHROME; |
| 386 chrome.developerPrivate.updateExtensionCommand( | 390 chrome.developerPrivate.updateExtensionCommand({ |
| 387 {extensionId: parsed.extensionId, | 391 extensionId: parsed.extensionId, |
| 388 commandName: parsed.commandName, | 392 commandName: parsed.commandName, |
| 389 scope: scope}); | 393 scope: scope |
| 394 }); |
| 390 }, | 395 }, |
| 391 | 396 |
| 392 /** | 397 /** |
| 393 * A utility function to create a unique element id based on a namespace, | 398 * A utility function to create a unique element id based on a namespace, |
| 394 * extension id and a command name. | 399 * extension id and a command name. |
| 395 * @param {string} namespace The namespace to prepend the id with. | 400 * @param {string} namespace The namespace to prepend the id with. |
| 396 * @param {string} extensionId The extension ID to use in the id. | 401 * @param {string} extensionId The extension ID to use in the id. |
| 397 * @param {string} commandName The command name to append the id with. | 402 * @param {string} commandName The command name to append the id with. |
| 398 * @private | 403 * @private |
| 399 */ | 404 */ |
| 400 createElementId_: function(namespace, extensionId, commandName) { | 405 createElementId_: function(namespace, extensionId, commandName) { |
| 401 return namespace + '-' + extensionId + '-' + commandName; | 406 return namespace + '-' + extensionId + '-' + commandName; |
| 402 }, | 407 }, |
| 403 | 408 |
| 404 /** | 409 /** |
| 405 * A utility function to parse a unique element id based on a namespace, | 410 * A utility function to parse a unique element id based on a namespace, |
| 406 * extension id and a command name. | 411 * extension id and a command name. |
| 407 * @param {string} namespace The namespace to prepend the id with. | 412 * @param {string} namespace The namespace to prepend the id with. |
| 408 * @param {string} id The id to parse. | 413 * @param {string} id The id to parse. |
| 409 * @return {{extensionId: string, commandName: string}} The parsed id. | 414 * @return {{extensionId: string, commandName: string}} The parsed id. |
| 410 * @private | 415 * @private |
| 411 */ | 416 */ |
| 412 parseElementId_: function(namespace, id) { | 417 parseElementId_: function(namespace, id) { |
| 413 var kExtensionIdLength = 32; | 418 var kExtensionIdLength = 32; |
| 414 return { | 419 return { |
| 415 extensionId: id.substring(namespace.length + 1, | 420 extensionId: id.substring( |
| 416 namespace.length + 1 + kExtensionIdLength), | 421 namespace.length + 1, namespace.length + 1 + kExtensionIdLength), |
| 417 commandName: id.substring(namespace.length + 1 + kExtensionIdLength + 1) | 422 commandName: id.substring(namespace.length + 1 + kExtensionIdLength + 1) |
| 418 }; | 423 }; |
| 419 }, | 424 }, |
| 420 }; | 425 }; |
| 421 | 426 |
| 422 return { | 427 return {ExtensionCommandList: ExtensionCommandList}; |
| 423 ExtensionCommandList: ExtensionCommandList | |
| 424 }; | |
| 425 }); | 428 }); |
| OLD | NEW |