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 |