Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Unified Diff: chrome/browser/resources/extensions/extension_command_list.js

Issue 10514003: Config UI for Extension Commands (part 1). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/extensions/extension_command_list.js
===================================================================
--- chrome/browser/resources/extensions/extension_command_list.js (revision 140271)
+++ chrome/browser/resources/extensions/extension_command_list.js (working copy)
@@ -13,9 +13,65 @@
*/
var ExtensionCommandList = cr.ui.define('div');
+ /**
+ * Returns whether the passed in |keyCode| is a valid extension command
+ * char or not. This is restricted to A-Z and 0-9 (ignoring modifiers) at
+ * the moment.
+ * @param {int} keyCode The keycode to consider.
+ * @return {boolean} Returns whether the char is valid.
+ */
+ function validChar(keyCode) {
+ return (keyCode >= 'A'.charCodeAt(0) && keyCode <= 'Z'.charCodeAt(0)) ||
+ (keyCode >= '0'.charCodeAt(0) && keyCode <= '9'.charCodeAt(0));
+ }
+
+ /**
+ * Convert a keystroke event to string form, while taking into account
+ * (ignoring) invalid extension commands.
+ * @param {Event} event The keyboard event to convert.
+ * @return {string} The keystroke as a string.
+ */
+ function keystrokeToString(event) {
+ var output = '';
+ if (event.ctrlKey)
+ output = 'Ctrl + ';
+ if (!event.ctrlKey && event.altKey)
+ output += 'Alt + ';
+ if (event.shiftKey)
+ output += 'Shift + ';
+ if (validChar(event.keyCode))
+ output += String.fromCharCode('A'.charCodeAt(0) + event.keyCode - 65);
+ return output;
+ }
+
ExtensionCommandList.prototype = {
__proto__: HTMLDivElement.prototype,
+ /**
+ * While capturing, this records the current (last) keyboard event generated
+ * by the user. Will be |null| after capture and during capture when no
+ * keyboard event has been generated.
+ * @type: {keyboard event}.
+ * @private
+ */
+ currentKeyEvent_: null,
+
+ /**
+ * While capturing, this keeps track of the previous selection so we can
+ * revert back to if no valid assignment is made during capture.
+ * @type: {string}.
+ * @private
+ */
+ oldValue_: '',
+
+ /**
+ * While capturing, this keeps track of which element the user asked to
+ * change.
+ * @type: {HTMLElement}.
+ * @private
+ */
+ capturingElement_: null,
+
/** @inheritDoc */
decorate: function() {
this.textContent = '';
@@ -59,17 +115,137 @@
var description = node.querySelector('.command-description');
description.textContent = command.description;
- var shortcut = node.querySelector('.command-shortcut');
+ var command_shortcut = node.querySelector('.command-shortcut');
+ command_shortcut.addEventListener('mouseup',
+ this.startCapture_.bind(this));
+ command_shortcut.addEventListener('blur', this.endCapture_.bind(this));
+ command_shortcut.addEventListener('keydown',
+ this.handleKeyDown_.bind(this));
+ command_shortcut.addEventListener('keyup', this.handleKeyUp_.bind(this));
+
if (!command.active) {
- shortcut.textContent =
+ command_shortcut.textContent =
loadTimeData.getString('extensionCommandsInactive');
- shortcut.classList.add('inactive-keybinding');
+ command_shortcut.classList.add('inactive-keybinding');
} else {
- shortcut.textContent = command.keybinding;
+ command_shortcut.textContent = command.keybinding;
}
this.appendChild(node);
},
+
+ /**
+ * Starts keystroke capture to determine which key to use for a particular
+ * extension command.
+ * @param {Event} event The keyboard event to consider.
+ * @private
+ */
+ startCapture_: function(event) {
+ if (this.capturingElement_)
+ return; // Already capturing.
+
+ chrome.send('setShortcutHandlingSuspended', [true]);
+
+ this.oldValue_ = event.target.textContent;
+ event.target.textContent =
+ loadTimeData.getString('extensionCommandsStartTyping');
+ event.target.classList.add('capturing');
+
+ this.capturingElement_ = event.target;
+ },
+
+ /**
+ * Ends keystroke capture and either restores the old value or (if valid
+ * value) sets the new value as active..
+ * @param {Event} event The keyboard event to consider.
+ * @private
+ */
+ endCapture_: function(event) {
+ if (!this.capturingElement_)
+ return; // Not capturing.
+
+ chrome.send('setShortcutHandlingSuspended', [false]);
+
+ this.capturingElement_.classList.remove('capturing');
+ this.capturingElement_.classList.remove('contains-chars');
+ if (!this.currentKeyEvent_ || !validChar(this.currentKeyEvent_.keyCode))
+ this.capturingElement_.textContent = this.oldValue_;
+
+ if (this.oldValue_ == '')
+ this.capturingElement_.classList.remove('clearable');
+ else
+ this.capturingElement_.classList.add('clearable');
+
+ this.oldValue_ = '';
+ this.capturingElement_ = null;
+ this.currentKeyEvent_ = null;
+ },
+
+ /**
+ * The KeyDown handler.
+ * @param {Event} event The keyboard event to consider.
+ * @private
+ */
+ handleKeyDown_: function(event) {
+ if (!this.capturingElement_)
+ this.startCapture_(event);
+
+ this.handleKey_(event);
+ },
+
+ /**
+ * The KeyUp handler.
+ * @param {Event} event The keyboard event to consider.
+ * @private
+ */
+ handleKeyUp_: function(event) {
+ // We want to make it easy to change from Ctrl+Shift+ to just Ctrl+ by
+ // releasing Shift, but we also don't want it to be easy to lose for
+ // example Ctrl+Shift+F to Ctrl+ just because you didn't release Ctrl
+ // as fast as the other two keys. Therefore, we process KeyUp until you
+ // have a valid combination and then stop processing it (meaning that once
+ // you have a valid combination, we won't change it until the next
+ // KeyDown message arrives).
+ if (!this.currentKeyEvent_ || !validChar(this.currentKeyEvent_.keyCode)) {
+ if (!event.ctrlKey && !event.altKey) {
+ // If neither Ctrl nor Alt is pressed then it is not a valid shortcut.
+ // That means we're back at the starting point so we should restart
+ // capture.
+ this.endCapture_(event);
+ this.startCapture_(event);
+ } else {
+ this.handleKey_(event);
+ }
+ }
+ },
+
+ /**
+ * A general key handler (used for both KeyDown and KeyUp).
+ * @param {Event} event The keyboard event to consider.
+ * @private
+ */
+ handleKey_: function(event) {
+ // While capturing, we prevent all events from bubbling, to prevent
+ // shortcuts lacking the right modifier (F3 for example) from activating
+ // and ending capture prematurely.
+ event.preventDefault();
+ event.stopPropagation();
+
+ if (!event.ctrlKey && !event.altKey)
+ return; // Ctrl or Alt is a must.
+
+ var keystroke = keystrokeToString(event);
+ event.target.textContent = keystroke;
+ event.target.classList.add('contains-chars');
+
+ if (validChar(event.keyCode)) {
+ this.oldValue_ = keystroke; // Forget what the old value was.
+ chrome.send('setExtensionCommandShortcut', ['id', keystroke]);
+ this.endCapture_(event);
+ }
+
+ this.currentKeyEvent_ = event;
+ },
};
return {

Powered by Google App Engine
This is Rietveld 408576698