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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 cr.define('options', function() { 5 cr.define('options', function() {
6 'use strict'; 6 'use strict';
7 7
8 /** 8 /**
9 * Creates a new list of extension commands. 9 * Creates a new list of extension commands.
10 * @param {Object=} opt_propertyBag Optional properties. 10 * @param {Object=} opt_propertyBag Optional properties.
11 * @constructor 11 * @constructor
12 * @extends {cr.ui.div} 12 * @extends {cr.ui.div}
13 */ 13 */
14 var ExtensionCommandList = cr.ui.define('div'); 14 var ExtensionCommandList = cr.ui.define('div');
15 15
16 /**
17 * While capturing, this records the current (last) keyboard event generated
18 * by the user. Will be |null| after capture and during capture when no
19 * keyboard event has been generated.
20 */
21 var currentKeyEvent = null;
22
23 /**
24 * While capturing, this keeps track of the previous selection so we can
25 * revert back to if no valid assignment is made during capture.
26 */
27 var oldValue = '';
28
29 /**
30 * While capturing, this keeps track of which element the user asked to
31 * change.
32 */
33 var capturingElement = null;
34
16 ExtensionCommandList.prototype = { 35 ExtensionCommandList.prototype = {
17 __proto__: HTMLDivElement.prototype, 36 __proto__: HTMLDivElement.prototype,
18 37
19 /** @inheritDoc */ 38 /** @inheritDoc */
20 decorate: function() { 39 decorate: function() {
21 this.textContent = ''; 40 this.textContent = '';
22 41
23 // Iterate over the extension data and add each item to the list. 42 // Iterate over the extension data and add each item to the list.
24 this.data_.commands.forEach(this.createNodeForExtension_.bind(this)); 43 this.data_.commands.forEach(this.createNodeForExtension_.bind(this));
25 }, 44 },
(...skipping 26 matching lines...) Expand all
52 * @private 71 * @private
53 */ 72 */
54 createNodeForCommand_: function(command) { 73 createNodeForCommand_: function(command) {
55 var template = $('template-collection-extension-commands').querySelector( 74 var template = $('template-collection-extension-commands').querySelector(
56 '.extension-command-list-command-item-wrapper'); 75 '.extension-command-list-command-item-wrapper');
57 var node = template.cloneNode(true); 76 var node = template.cloneNode(true);
58 77
59 var description = node.querySelector('.command-description'); 78 var description = node.querySelector('.command-description');
60 description.textContent = command.description; 79 description.textContent = command.description;
61 80
62 var shortcut = node.querySelector('.command-shortcut'); 81 var command_shortcut = node.querySelector('.command-shortcut');
82 command_shortcut.addEventListener('mouseup',
83 this.startCapture_.bind(this));
84 command_shortcut.addEventListener('blur', this.endCapture_.bind(this));
85 command_shortcut.addEventListener('keydown',
86 this.handleKeyDown_.bind(this));
87 command_shortcut.addEventListener('keyup', this.handleKeyUp_.bind(this));
88
63 if (!command.active) { 89 if (!command.active) {
64 shortcut.textContent = 90 command_shortcut.textContent =
65 loadTimeData.getString('extensionCommandsInactive'); 91 loadTimeData.getString('extensionCommandsInactive');
66 shortcut.classList.add('inactive-keybinding'); 92 command_shortcut.classList.add('inactive-keybinding');
67 } else { 93 } else {
68 shortcut.textContent = command.keybinding; 94 command_shortcut.textContent = command.keybinding;
69 } 95 }
70 96
71 this.appendChild(node); 97 this.appendChild(node);
72 }, 98 },
99
100 /**
101 * Convert a keystroke event to string form, while taking into account
102 * (ignoring) invalid extension commands.
103 * @param {Event} event The keyboard event to convert.
104 * @private
105 */
106 keystrokeToString_: function(event) {
107 var output = event.ctrlKey ? 'Ctrl + ' : '';
108 if (!event.ctrlKey)
109 output += event.altKey ? 'Alt + ' : '';
110 output += event.shiftKey ? 'Shift + ' : '';
Evan Stade 2012/06/05 00:20:37 imo, it's easier to read if (event.fooKey) outp
111 if (this.validChar_(event.keyCode))
112 output += String.fromCharCode('A'.charCodeAt(0) + event.keyCode - 65);
113 return output;
114 },
115
116 /**
117 * Returns whether the passed in |keyCode| is a valid extension command
118 * char or not. This is restricted to A-Z and 0-9 (ignoring modifiers) at
119 * the moment.
120 * @param {int} keyCode The keycode to consider.
121 * @private
122 */
123 validChar_: function(keyCode) {
124 return (keyCode >= 'A'.charCodeAt(0) && keyCode <= 'Z'.charCodeAt(0)) ||
125 (keyCode >= '0'.charCodeAt(0) && keyCode <= '9'.charCodeAt(0));
126 },
127
128 /**
129 * Starts keystroke capture to determine which key to use for a particular
130 * extension command.
131 * @param {Event} event The keyboard event to consider.
132 * @private
133 */
134 startCapture_: function(event) {
135 if (capturingElement !== null)
136 return; // Already capturing.
137
138 chrome.send('setShortcutHandlingSuspended', [true]);
139
140 oldValue = event.target.textContent;
141 event.target.textContent =
142 loadTimeData.getString('extensionCommandsStartTyping');
143 event.target.classList.add('capturing');
144
145 capturingElement = event.target;
146 },
147
148 /**
149 * Ends keystroke capture and either restores the old value or (if valid
150 * value) sets the new value as active..
151 * @param {Event} event The keyboard event to consider.
152 * @private
153 */
154 endCapture_: function(event) {
155 if (capturingElement === null)
156 return; // Not capturing.
157
158 chrome.send('setShortcutHandlingSuspended', [false]);
159
160 capturingElement.classList.remove('capturing');
161 capturingElement.classList.remove('contains-chars');
162 if (currentKeyEvent == null ||
163 !this.validChar_(currentKeyEvent.keyCode))
164 capturingElement.textContent = oldValue;
165
166 if (oldValue == '')
167 capturingElement.classList.remove('clearable');
168 else
169 capturingElement.classList.add('clearable');
170
171 oldValue = '';
172 capturingElement = null;
173 currentKeyEvent = null;
174 },
175
176 /**
177 * The KeyDown handler.
178 * @param {Event} event The keyboard event to consider.
179 * @private
180 */
181 handleKeyDown_: function(event) {
182 if (capturingElement === null)
183 this.startCapture_(event);
184
185 this.handleKey_(event);
186 },
187
188 /**
189 * The KeyUp handler.
190 * @param {Event} event The keyboard event to consider.
191 * @private
192 */
193 handleKeyUp_: function(event) {
194 // We want to make it easy to change from Ctrl+Shift+ to just Ctrl+ by
195 // releasing Shift, but we also don't want it to be easy to loose for
196 // example Ctrl+Shift+F to Ctrl+ just because you didn't release Ctrl
197 // as fast as the other two keys. Therefore, we process KeyUp until you
198 // have a valid combination and then stop processing it (meaning that once
199 // you have a valid combination, we won't change it until the next
200 // KeyDown message arrives).
201 if (currentKeyEvent === null ||
202 !this.validChar_(currentKeyEvent.keyCode)) {
203 if (!event.ctrlKey && !event.altKey) {
204 // If neither Ctrl nor Alt is pressed then it is not a valid shortcut.
205 // That means we're back at the starting point so we should restart
206 // capture.
207 this.endCapture_(event);
208 this.startCapture_(event);
209 } else {
210 this.handleKey_(event);
211 }
212 }
213 },
214
215 /**
216 * A general key handler (used for both KeyDown and KeyUp).
217 * @param {Event} event The keyboard event to consider.
218 * @private
219 */
220 handleKey_: function(event) {
221 // While capturing, we prevent all events from bubbling, to prevent
222 // shortcuts lacking the right modifier (F3 for example) from activating
223 // and ending capture prematurely.
224 event.preventDefault();
225
226 if (!event.ctrlKey && !event.altKey)
227 return true; // Ctrl or Alt is a must.
228
229 var keystroke = this.keystrokeToString_(event);
230 event.target.textContent = keystroke;
231 event.target.classList.add('contains-chars');
232 currentKeyEvent = event;
233
234 if (this.validChar_(event.keyCode)) {
235 oldValue = keystroke; // Forget what the old value was.
236 chrome.send('setExtensionCommandShortcut', ['id', keystroke]);
237 this.endCapture_(event);
238 }
239
240 return false;
241 },
73 }; 242 };
74 243
75 return { 244 return {
76 ExtensionCommandList: ExtensionCommandList 245 ExtensionCommandList: ExtensionCommandList
77 }; 246 };
78 }); 247 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698