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 /** @typedef {{active: boolean, | |
6 * command_name: string, | |
7 * description: string, | |
8 * extension_action: boolean, | |
9 * extension_id: string, | |
10 * global: boolean, | |
11 * keybinding: string}} | |
12 */ | |
13 var CommandBackendObject; | |
Dan Beam
2014/08/21 18:27:47
ExtensionCommand
Vitaly Pavlenko
2014/08/22 01:43:39
Done.
| |
14 | |
5 cr.define('options', function() { | 15 cr.define('options', function() { |
6 'use strict'; | 16 'use strict'; |
7 | 17 |
8 /** | 18 /** |
9 * Creates a new list of extension commands. | 19 * Creates a new list of extension commands. |
10 * @param {Object=} opt_propertyBag Optional properties. | 20 * @param {Object=} opt_propertyBag Optional properties. |
11 * @constructor | 21 * @constructor |
12 * @extends {cr.ui.div} | 22 * @extends {HTMLDivElement} |
13 */ | 23 */ |
14 var ExtensionCommandList = cr.ui.define('div'); | 24 var ExtensionCommandList = cr.ui.define('div'); |
15 | 25 |
16 /** @const */ var keyComma = 188; | 26 /** @const */ var keyComma = 188; |
17 /** @const */ var keyDel = 46; | 27 /** @const */ var keyDel = 46; |
18 /** @const */ var keyDown = 40; | 28 /** @const */ var keyDown = 40; |
19 /** @const */ var keyEnd = 35; | 29 /** @const */ var keyEnd = 35; |
20 /** @const */ var keyEscape = 27; | 30 /** @const */ var keyEscape = 27; |
21 /** @const */ var keyHome = 36; | 31 /** @const */ var keyHome = 36; |
22 /** @const */ var keyIns = 45; | 32 /** @const */ var keyIns = 45; |
(...skipping 15 matching lines...) Expand all Loading... | |
38 */ | 48 */ |
39 var Modifiers = { | 49 var Modifiers = { |
40 ARE_NOT_ALLOWED: 0, | 50 ARE_NOT_ALLOWED: 0, |
41 ARE_REQUIRED: 1 | 51 ARE_REQUIRED: 1 |
42 }; | 52 }; |
43 | 53 |
44 /** | 54 /** |
45 * Returns whether the passed in |keyCode| is a valid extension command | 55 * Returns whether the passed in |keyCode| is a valid extension command |
46 * char or not. This is restricted to A-Z and 0-9 (ignoring modifiers) at | 56 * char or not. This is restricted to A-Z and 0-9 (ignoring modifiers) at |
47 * the moment. | 57 * the moment. |
48 * @param {int} keyCode The keycode to consider. | 58 * @param {number} keyCode The keycode to consider. |
49 * @return {boolean} Returns whether the char is valid. | 59 * @return {boolean} Returns whether the char is valid. |
50 */ | 60 */ |
51 function validChar(keyCode) { | 61 function validChar(keyCode) { |
52 return keyCode == keyComma || | 62 return keyCode == keyComma || |
53 keyCode == keyDel || | 63 keyCode == keyDel || |
54 keyCode == keyDown || | 64 keyCode == keyDown || |
55 keyCode == keyEnd || | 65 keyCode == keyEnd || |
56 keyCode == keyHome || | 66 keyCode == keyHome || |
57 keyCode == keyIns || | 67 keyCode == keyIns || |
58 keyCode == keyLeft || | 68 keyCode == keyLeft || |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
132 } | 142 } |
133 } | 143 } |
134 | 144 |
135 return output; | 145 return output; |
136 } | 146 } |
137 | 147 |
138 /** | 148 /** |
139 * Returns whether the passed in |keyCode| require modifiers. Currently only | 149 * Returns whether the passed in |keyCode| require modifiers. Currently only |
140 * "MediaNextTrack", "MediaPrevTrack", "MediaStop", "MediaPlayPause" are | 150 * "MediaNextTrack", "MediaPrevTrack", "MediaStop", "MediaPlayPause" are |
141 * required to be used without any modifier. | 151 * required to be used without any modifier. |
142 * @param {int} keyCode The keycode to consider. | 152 * @param {number} keyCode The keycode to consider. |
143 * @return {Modifiers} Returns whether the keycode require modifiers. | 153 * @return {Modifiers} Returns whether the keycode require modifiers. |
144 */ | 154 */ |
145 function modifiers(keyCode) { | 155 function modifiers(keyCode) { |
146 switch (keyCode) { | 156 switch (keyCode) { |
147 case keyMediaNextTrack: | 157 case keyMediaNextTrack: |
148 case keyMediaPlayPause: | 158 case keyMediaPlayPause: |
149 case keyMediaPrevTrack: | 159 case keyMediaPrevTrack: |
150 case keyMediaStop: | 160 case keyMediaStop: |
151 return Modifiers.ARE_NOT_ALLOWED; | 161 return Modifiers.ARE_NOT_ALLOWED; |
152 default: | 162 default: |
(...skipping 14 matching lines...) Expand all Loading... | |
167 (countShiftAsModifier && event.shiftKey); | 177 (countShiftAsModifier && event.shiftKey); |
168 } | 178 } |
169 | 179 |
170 ExtensionCommandList.prototype = { | 180 ExtensionCommandList.prototype = { |
171 __proto__: HTMLDivElement.prototype, | 181 __proto__: HTMLDivElement.prototype, |
172 | 182 |
173 /** | 183 /** |
174 * While capturing, this records the current (last) keyboard event generated | 184 * While capturing, this records the current (last) keyboard event generated |
175 * by the user. Will be |null| after capture and during capture when no | 185 * by the user. Will be |null| after capture and during capture when no |
176 * keyboard event has been generated. | 186 * keyboard event has been generated. |
177 * @type: {keyboard event}. | 187 * @type {KeyboardEvent}. |
178 * @private | 188 * @private |
179 */ | 189 */ |
180 currentKeyEvent_: null, | 190 currentKeyEvent_: null, |
181 | 191 |
182 /** | 192 /** |
183 * While capturing, this keeps track of the previous selection so we can | 193 * While capturing, this keeps track of the previous selection so we can |
184 * revert back to if no valid assignment is made during capture. | 194 * revert back to if no valid assignment is made during capture. |
185 * @type: {string}. | 195 * @type {string}. |
186 * @private | 196 * @private |
187 */ | 197 */ |
188 oldValue_: '', | 198 oldValue_: '', |
189 | 199 |
190 /** | 200 /** |
191 * While capturing, this keeps track of which element the user asked to | 201 * While capturing, this keeps track of which element the user asked to |
192 * change. | 202 * change. |
193 * @type: {HTMLElement}. | 203 * @type {HTMLElement}. |
194 * @private | 204 * @private |
195 */ | 205 */ |
196 capturingElement_: null, | 206 capturingElement_: null, |
197 | 207 |
198 /** @override */ | 208 /** @override */ |
199 decorate: function() { | 209 decorate: function() { |
200 this.textContent = ''; | 210 this.textContent = ''; |
201 | 211 |
202 // Iterate over the extension data and add each item to the list. | 212 // Iterate over the extension data and add each item to the list. |
203 this.data_.commands.forEach(this.createNodeForExtension_.bind(this)); | 213 this.data_.commands.forEach(this.createNodeForExtension_.bind(this)); |
(...skipping 16 matching lines...) Expand all Loading... | |
220 this.appendChild(node); | 230 this.appendChild(node); |
221 | 231 |
222 // Iterate over the commands data within the extension and add each item | 232 // Iterate over the commands data within the extension and add each item |
223 // to the list. | 233 // to the list. |
224 extension.commands.forEach(this.createNodeForCommand_.bind(this)); | 234 extension.commands.forEach(this.createNodeForCommand_.bind(this)); |
225 }, | 235 }, |
226 | 236 |
227 /** | 237 /** |
228 * Synthesizes and initializes an HTML element for the extension command | 238 * Synthesizes and initializes an HTML element for the extension command |
229 * metadata given in |command|. | 239 * metadata given in |command|. |
230 * @param {Object} command A dictionary of extension command metadata. | 240 * @param {CommandBackendObject} command A dictionary of extension command |
241 * metadata. | |
231 * @private | 242 * @private |
232 */ | 243 */ |
233 createNodeForCommand_: function(command) { | 244 createNodeForCommand_: function(command) { |
234 var template = $('template-collection-extension-commands').querySelector( | 245 var template = $('template-collection-extension-commands').querySelector( |
235 '.extension-command-list-command-item-wrapper'); | 246 '.extension-command-list-command-item-wrapper'); |
236 var node = template.cloneNode(true); | 247 var node = template.cloneNode(true); |
237 node.id = this.createElementId_( | 248 node.id = this.createElementId_( |
238 'command', command.extension_id, command.command_name); | 249 'command', command.extension_id, command.command_name); |
239 | 250 |
240 var description = node.querySelector('.command-description'); | 251 var description = node.querySelector('.command-description'); |
241 description.textContent = command.description; | 252 description.textContent = command.description; |
242 | 253 |
243 var shortcutNode = node.querySelector('.command-shortcut-text'); | 254 var shortcutNode = node.querySelector('.command-shortcut-text'); |
244 shortcutNode.addEventListener('mouseup', | 255 shortcutNode.addEventListener('mouseup', |
245 this.startCapture_.bind(this)); | 256 this.startCapture_.bind(this)); |
246 shortcutNode.addEventListener('focus', this.handleFocus_.bind(this)); | 257 shortcutNode.addEventListener('focus', this.handleFocus_.bind(this)); |
247 shortcutNode.addEventListener('blur', this.handleBlur_.bind(this)); | 258 shortcutNode.addEventListener('blur', this.handleBlur_.bind(this)); |
248 shortcutNode.addEventListener('keydown', | 259 shortcutNode.addEventListener('keydown', /** @type {function(Event)} */( |
Dan Beam
2014/08/21 18:27:47
cast the event later
Vitaly Pavlenko
2014/08/22 01:43:39
Done.
| |
249 this.handleKeyDown_.bind(this)); | 260 this.handleKeyDown_.bind(this))); |
250 shortcutNode.addEventListener('keyup', this.handleKeyUp_.bind(this)); | 261 shortcutNode.addEventListener('keyup', /** @type {function (Event)} */( |
262 this.handleKeyUp_.bind(this))); | |
251 if (!command.active) { | 263 if (!command.active) { |
252 shortcutNode.textContent = | 264 shortcutNode.textContent = |
253 loadTimeData.getString('extensionCommandsInactive'); | 265 loadTimeData.getString('extensionCommandsInactive'); |
254 | 266 |
255 var commandShortcut = node.querySelector('.command-shortcut'); | 267 var commandShortcut = node.querySelector('.command-shortcut'); |
256 commandShortcut.classList.add('inactive-keybinding'); | 268 commandShortcut.classList.add('inactive-keybinding'); |
257 } else { | 269 } else { |
258 shortcutNode.textContent = command.keybinding; | 270 shortcutNode.textContent = command.keybinding; |
259 } | 271 } |
260 | 272 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
305 var shortcutNode = event.target; | 317 var shortcutNode = event.target; |
306 this.oldValue_ = shortcutNode.textContent; | 318 this.oldValue_ = shortcutNode.textContent; |
307 shortcutNode.textContent = | 319 shortcutNode.textContent = |
308 loadTimeData.getString('extensionCommandsStartTyping'); | 320 loadTimeData.getString('extensionCommandsStartTyping'); |
309 shortcutNode.parentElement.classList.add('capturing'); | 321 shortcutNode.parentElement.classList.add('capturing'); |
310 | 322 |
311 var commandClear = | 323 var commandClear = |
312 shortcutNode.parentElement.querySelector('.command-clear'); | 324 shortcutNode.parentElement.querySelector('.command-clear'); |
313 commandClear.hidden = true; | 325 commandClear.hidden = true; |
314 | 326 |
315 this.capturingElement_ = event.target; | 327 this.capturingElement_ = /** @type {HTMLElement} */(event.target); |
316 }, | 328 }, |
317 | 329 |
318 /** | 330 /** |
319 * Ends keystroke capture and either restores the old value or (if valid | 331 * Ends keystroke capture and either restores the old value or (if valid |
320 * value) sets the new value as active.. | 332 * value) sets the new value as active.. |
321 * @param {Event} event The keyboard event to consider. | 333 * @param {Event} event The keyboard event to consider. |
322 * @private | 334 * @private |
323 */ | 335 */ |
324 endCapture_: function(event) { | 336 endCapture_: function(event) { |
325 if (!this.capturingElement_) | 337 if (!this.capturingElement_) |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 * @private | 385 * @private |
374 */ | 386 */ |
375 handleBlur_: function(event) { | 387 handleBlur_: function(event) { |
376 this.endCapture_(event); | 388 this.endCapture_(event); |
377 var commandShortcut = event.target.parentElement; | 389 var commandShortcut = event.target.parentElement; |
378 commandShortcut.classList.remove('focused'); | 390 commandShortcut.classList.remove('focused'); |
379 }, | 391 }, |
380 | 392 |
381 /** | 393 /** |
382 * The KeyDown handler. | 394 * The KeyDown handler. |
383 * @param {Event} event The keyboard event to consider. | 395 * @param {KeyboardEvent} event The keyboard event to consider. |
384 * @private | 396 * @private |
385 */ | 397 */ |
386 handleKeyDown_: function(event) { | 398 handleKeyDown_: function(event) { |
387 if (event.keyCode == keyEscape) { | 399 if (event.keyCode == keyEscape) { |
388 // Escape cancels capturing. | 400 // Escape cancels capturing. |
389 this.endCapture_(event); | 401 this.endCapture_(event); |
390 var parsed = this.parseElementId_('clear', | 402 var parsed = this.parseElementId_('clear', |
391 event.target.parentElement.querySelector('.command-clear').id); | 403 event.target.parentElement.querySelector('.command-clear').id); |
392 chrome.send('setExtensionCommandShortcut', | 404 chrome.send('setExtensionCommandShortcut', |
393 [parsed.extensionId, parsed.commandName, '']); | 405 [parsed.extensionId, parsed.commandName, '']); |
394 event.preventDefault(); | 406 event.preventDefault(); |
395 event.stopPropagation(); | 407 event.stopPropagation(); |
396 return; | 408 return; |
397 } | 409 } |
398 if (event.keyCode == keyTab) { | 410 if (event.keyCode == keyTab) { |
399 // Allow tab propagation for keyboard navigation. | 411 // Allow tab propagation for keyboard navigation. |
400 return; | 412 return; |
401 } | 413 } |
402 | 414 |
403 if (!this.capturingElement_) | 415 if (!this.capturingElement_) |
404 this.startCapture_(event); | 416 this.startCapture_(event); |
405 | 417 |
406 this.handleKey_(event); | 418 this.handleKey_(event); |
407 }, | 419 }, |
408 | 420 |
409 /** | 421 /** |
410 * The KeyUp handler. | 422 * The KeyUp handler. |
411 * @param {Event} event The keyboard event to consider. | 423 * @param {KeyboardEvent} event The keyboard event to consider. |
412 * @private | 424 * @private |
413 */ | 425 */ |
414 handleKeyUp_: function(event) { | 426 handleKeyUp_: function(event) { |
415 if (event.keyCode == keyTab) { | 427 if (event.keyCode == keyTab) { |
416 // Allow tab propagation for keyboard navigation. | 428 // Allow tab propagation for keyboard navigation. |
417 return; | 429 return; |
418 } | 430 } |
419 | 431 |
420 // We want to make it easy to change from Ctrl+Shift+ to just Ctrl+ by | 432 // We want to make it easy to change from Ctrl+Shift+ to just Ctrl+ by |
421 // releasing Shift, but we also don't want it to be easy to lose for | 433 // releasing Shift, but we also don't want it to be easy to lose for |
(...skipping 10 matching lines...) Expand all Loading... | |
432 this.endCapture_(event); | 444 this.endCapture_(event); |
433 this.startCapture_(event); | 445 this.startCapture_(event); |
434 } else { | 446 } else { |
435 this.handleKey_(event); | 447 this.handleKey_(event); |
436 } | 448 } |
437 } | 449 } |
438 }, | 450 }, |
439 | 451 |
440 /** | 452 /** |
441 * A general key handler (used for both KeyDown and KeyUp). | 453 * A general key handler (used for both KeyDown and KeyUp). |
442 * @param {Event} event The keyboard event to consider. | 454 * @param {KeyboardEvent} event The keyboard event to consider. |
443 * @private | 455 * @private |
444 */ | 456 */ |
445 handleKey_: function(event) { | 457 handleKey_: function(event) { |
446 // While capturing, we prevent all events from bubbling, to prevent | 458 // While capturing, we prevent all events from bubbling, to prevent |
447 // shortcuts lacking the right modifier (F3 for example) from activating | 459 // shortcuts lacking the right modifier (F3 for example) from activating |
448 // and ending capture prematurely. | 460 // and ending capture prematurely. |
449 event.preventDefault(); | 461 event.preventDefault(); |
450 event.stopPropagation(); | 462 event.stopPropagation(); |
451 | 463 |
452 if (modifiers(event.keyCode) == Modifiers.ARE_REQUIRED && | 464 if (modifiers(event.keyCode) == Modifiers.ARE_REQUIRED && |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
516 */ | 528 */ |
517 createElementId_: function(namespace, extensionId, commandName) { | 529 createElementId_: function(namespace, extensionId, commandName) { |
518 return namespace + '-' + extensionId + '-' + commandName; | 530 return namespace + '-' + extensionId + '-' + commandName; |
519 }, | 531 }, |
520 | 532 |
521 /** | 533 /** |
522 * A utility function to parse a unique element id based on a namespace, | 534 * A utility function to parse a unique element id based on a namespace, |
523 * extension id and a command name. | 535 * extension id and a command name. |
524 * @param {string} namespace The namespace to prepend the id with. | 536 * @param {string} namespace The namespace to prepend the id with. |
525 * @param {string} id The id to parse. | 537 * @param {string} id The id to parse. |
526 * @return {object} The parsed id, as an object with two members: | 538 * @return {{extensionId: string, commandName: string}} The parsed id. |
527 * extensionID and commandName. | |
528 * @private | 539 * @private |
529 */ | 540 */ |
530 parseElementId_: function(namespace, id) { | 541 parseElementId_: function(namespace, id) { |
531 var kExtensionIdLength = 32; | 542 var kExtensionIdLength = 32; |
532 return { | 543 return { |
533 extensionId: id.substring(namespace.length + 1, | 544 extensionId: id.substring(namespace.length + 1, |
534 namespace.length + 1 + kExtensionIdLength), | 545 namespace.length + 1 + kExtensionIdLength), |
535 commandName: id.substring(namespace.length + 1 + kExtensionIdLength + 1) | 546 commandName: id.substring(namespace.length + 1 + kExtensionIdLength + 1) |
536 }; | 547 }; |
537 }, | 548 }, |
538 }; | 549 }; |
539 | 550 |
540 return { | 551 return { |
541 ExtensionCommandList: ExtensionCommandList | 552 ExtensionCommandList: ExtensionCommandList |
542 }; | 553 }; |
543 }); | 554 }); |
OLD | NEW |