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

Side by Side Diff: resources/bookmark_manager/js/cr/ui/command.js

Issue 853002: Updating the Chromium reference build for Windows. The continuous... (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/reference_builds/chrome/
Patch Set: Added the symbol files back. Created 10 years, 9 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
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6 * @fileoverview A command is an abstraction of an action a user can do in the
7 * UI.
8 *
9 * When the focus changes in the document for each command a canExecute event
10 * is dispatched on the active element. By listening to this event you can
11 * enable and disable the command by setting the event.canExecute property.
12 *
13 * When a command is executed a command event is dispatched on the active
14 * element. Note that you should stop the propagation after you have handled the
15 * command if there might be other command listeners higher up in the DOM tree.
16 */
17
18 cr.define('cr.ui', function() {
19
20 /**
21 * Creates a new command element.
22 * @constructor
23 * @extends {HTMLElement}
24 */
25 var Command = cr.ui.define('command');
26
27 Command.prototype = {
28 __proto__: HTMLElement.prototype,
29
30 /**
31 * Initializes the command.
32 */
33 decorate: function() {
34 CommandManager.init(this.ownerDocument);
35 },
36
37 /**
38 * Executes the command. This dispatches a command event on the active
39 * element. If the command is {@code disabled} this does nothing.
40 */
41 execute: function() {
42 if (this.disabled)
43 return;
44 var doc = this.ownerDocument;
45 if (doc.activeElement) {
46 var e = new cr.Event('command', true, false);
47 e.command = this;
48 doc.activeElement.dispatchEvent(e);
49 }
50 },
51
52 /**
53 * Call this when there have been changes that might change whether the
54 * command can be executed or not.
55 */
56 canExecuteChange: function() {
57 dispatchCanExecuteEvent(this, this.ownerDocument.activeElement);
58 },
59
60 /**
61 * The keyboard shortcut that triggers the command. This is a string
62 * consisting of a keyIdentifier (as reported by WebKit in keydown) as
63 * well as optional key modifiers joinded with a '-'.
64 * For example:
65 * "F1"
66 * "U+0008-Meta" for Apple command backspace.
67 * "U+0041-Ctrl" for Control A
68 *
69 * @type {string}
70 */
71 shortcut_: null,
72 get shortcut() {
73 return this.shortcut_;
74 },
75 set shortcut(shortcut) {
76 var oldShortcut = this.shortcut_;
77 if (shortcut !== oldShortcut) {
78 this.shortcut_ = shortcut;
79
80 // TODO(arv): Multiple shortcuts?
81
82 var mods = {};
83 var ident = '';
84 shortcut.split('-').forEach(function(part) {
85 var partLc = part.toLowerCase();
86 switch (partLc) {
87 case 'alt':
88 case 'ctrl':
89 case 'meta':
90 case 'shift':
91 mods[partLc + 'Key'] = true;
92 break;
93 default:
94 if (ident)
95 throw Error('Multiple keyboard shortcuts are not supported');
96 ident = part;
97 }
98
99 this.keyIdentifier_ = ident;
100 this.keyModifiers_ = mods;
101 }, this);
102
103 cr.dispatchPropertyChange(this, 'shortcut', this.shortcut_,
104 oldShortcut);
105 }
106 },
107
108 /**
109 * Whether the event object matches the shortcut for this command.
110 * @param {!Event} e The key event object.
111 * @return {boolean} Whether it matched or not.
112 */
113 matchesEvent: function(e) {
114 if (!this.keyIdentifier_)
115 return false;
116
117 if (e.keyIdentifier == this.keyIdentifier_) {
118 // All keyboard modifiers needs to match.
119 var mods = this.keyModifiers_;
120 return ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'].every(function(k) {
121 return e[k] == !!mods[k];
122 });
123 }
124 return false;
125 }
126 };
127
128 /**
129 * The label of the command.
130 * @type {string}
131 */
132 cr.defineProperty(Command, 'label', cr.PropertyKind.ATTR);
133
134 /**
135 * Whether the command is disabled or not.
136 * @type {boolean}
137 */
138 cr.defineProperty(Command, 'disabled', cr.PropertyKind.BOOL_ATTR);
139
140 /**
141 * Whether the command is hidden or not.
142 * @type {boolean}
143 */
144 cr.defineProperty(Command, 'hidden', cr.PropertyKind.BOOL_ATTR);
145
146 /**
147 * Dispatches a canExecute event on the target.
148 * @param {cr.ui.Command} command The command that we are testing for.
149 * @param {Element} target The target element to dispatch the event on.
150 */
151 function dispatchCanExecuteEvent(command, target) {
152 var e = new CanExecuteEvent(command, true)
153 target.dispatchEvent(e);
154 command.disabled = !e.canExecute;
155 }
156
157 /**
158 * The command managers for different documents.
159 */
160 var commandManagers = {};
161
162 /**
163 * Keeps track of the focused element and updates the commands when the focus
164 * changes.
165 * @param {!Document} doc The document that we are managing the commands for.
166 * @constructor
167 */
168 function CommandManager(doc) {
169 doc.addEventListener('focus', cr.bind(this.handleFocus_, this), true);
170 doc.addEventListener('keydown', cr.bind(this.handleKeyDown_, this), true);
171 }
172
173 /**
174 * Initializes a command manager for the document as needed.
175 * @param {!Document} doc The document to manage the commands for.
176 */
177 CommandManager.init = function(doc) {
178 var uid = cr.getUid(doc);
179 if (!(uid in commandManagers)) {
180 commandManagers[uid] = new CommandManager(doc);
181 }
182 },
183
184 CommandManager.prototype = {
185
186 /**
187 * Handles focus changes on the document.
188 * @param {Event} e The focus event object.
189 * @private
190 */
191 handleFocus_: function(e) {
192 var target = e.target;
193 var commands = Array.prototype.slice.call(
194 target.ownerDocument.querySelectorAll('command'));
195
196 commands.forEach(function(command) {
197 dispatchCanExecuteEvent(command, target);
198 });
199 },
200
201 /**
202 * Handles the keydown event and routes it to the right command.
203 * @param {!Event} e The keydown event.
204 */
205 handleKeyDown_: function(e) {
206 var target = e.target;
207 var commands = Array.prototype.slice.call(
208 target.ownerDocument.querySelectorAll('command'));
209
210 for (var i = 0, command; command = commands[i]; i++) {
211 if (!command.disabled && command.matchesEvent(e)) {
212 e.preventDefault();
213 // We do not want any other element to handle this.
214 e.stopPropagation();
215
216 command.execute();
217 return;
218 }
219 }
220 }
221 };
222
223 /**
224 * The event type used for canExecute events.
225 * @param {!cr.ui.Command} command The command that we are evaluating.
226 * @extends {Event}
227 */
228 function CanExecuteEvent(command) {
229 var e = command.ownerDocument.createEvent('Event');
230 e.initEvent('canExecute', true, false);
231 e.__proto__ = CanExecuteEvent.prototype;
232 e.command = command;
233 return e;
234 }
235
236 CanExecuteEvent.prototype = {
237 __proto__: Event.prototype,
238
239 /**
240 * The current command
241 * @type {cr.ui.Command}
242 */
243 command: null,
244
245 /**
246 * Whether the target can execute the command. Setting this also stops the
247 * propagation.
248 * @type {boolean}
249 */
250 canExecute_: false,
251 get canExecute() {
252 return this.canExecute_;
253 },
254 set canExecute(canExecute) {
255 this.canExecute_ = canExecute;
256 this.stopPropagation();
257 }
258 };
259
260 // Export
261 return {
262 Command: Command,
263 CanExecuteEvent: CanExecuteEvent
264 };
265 });
OLDNEW
« no previous file with comments | « resources/bookmark_manager/js/cr/ui.js ('k') | resources/bookmark_manager/js/cr/ui/contextmenuhandler.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698