blob: 75306626e470e1f874c069a438c9150b941a2752 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
cr.define('extensions', function() {
'use strict';
// The UI to display and manage keyboard shortcuts set for extension commands.
var ShortcutInput = Polymer({
is: 'extensions-shortcut-input',
behaviors: [I18nBehavior],
properties: {
item: {
type: String,
value: '',
},
commandName: {
type: String,
value: '',
},
shortcut: {
type: String,
value: '',
},
/** @private */
capturing_: {
type: Boolean,
value: false,
},
/** @private */
pendingShortcut_: {
type: String,
value: '',
},
},
ready: function() {
var node = this.$['input'];
node.addEventListener('mouseup', this.startCapture_.bind(this));
node.addEventListener('blur', this.endCapture_.bind(this));
node.addEventListener('focus', this.startCapture_.bind(this));
node.addEventListener('keydown', this.onKeyDown_.bind(this));
node.addEventListener('keyup', this.onKeyUp_.bind(this));
},
/** @private */
startCapture_: function() {
if (this.capturing_)
return;
this.capturing_ = true;
this.fire('shortcut-capture-started');
},
/** @private */
endCapture_: function() {
if (!this.capturing_)
return;
this.pendingShortcut_ = '';
this.capturing_ = false;
this.$['input'].blur();
this.fire('shortcut-capture-ended');
},
/**
* @param {!KeyboardEvent} e
* @private
*/
onKeyDown_: function(e) {
if (e.keyCode == extensions.Key.Escape) {
if (!this.capturing_) {
// If we're not currently capturing, allow escape to propagate.
return;
}
// Otherwise, escape cancels capturing.
this.endCapture_();
e.preventDefault();
e.stopPropagation();
return;
}
if (e.keyCode == extensions.Key.Tab) {
// Allow tab propagation for keyboard navigation.
return;
}
if (!this.capturing_)
this.startCapture_();
this.handleKey_(e);
},
/**
* @param {!KeyboardEvent} e
* @private
*/
onKeyUp_: function(e) {
if (e.keyCode == extensions.Key.Escape || e.keyCode == extensions.Key.Tab)
return;
this.handleKey_(e);
},
/**
* @param {!KeyboardEvent} e
* @private
*/
handleKey_: function(e) {
// While capturing, we prevent all events from bubbling, to prevent
// shortcuts lacking the right modifier (F3 for example) from activating
// and ending capture prematurely.
e.preventDefault();
e.stopPropagation();
// We don't allow both Ctrl and Alt in the same keybinding.
// TODO(devlin): This really should go in extensions.hasValidModifiers,
// but that requires updating the existing page as well.
if ((e.ctrlKey && e.altKey) || !extensions.hasValidModifiers(e)) {
this.pendingShortcut_ = 'invalid';
return;
}
this.pendingShortcut_ = extensions.keystrokeToString(e);
if (extensions.isValidKeyCode(e.keyCode)) {
this.commitPending_();
this.endCapture_();
}
},
/** @private */
commitPending_: function() {
this.shortcut = this.pendingShortcut_;
this.fire('shortcut-updated', {keybinding: this.shortcut,
item: this.item,
commandName: this.commandName});
},
/**
* @return {string} The text to be displayed in the shortcut field.
* @private
*/
computeText_: function() {
if (this.capturing_)
return this.pendingShortcut_ || this.i18n('shortcutTypeAShortcut');
return this.shortcut || this.i18n('shortcutNotSet');
},
/**
* @return {boolean} Whether the clear button is hidden.
* @private
*/
computeClearHidden_: function() {
// We don't want to show the clear button if the input is currently
// capturing a new shortcut or if there is no shortcut to clear.
return this.capturing_ || !this.shortcut;
},
/** @private */
onClearTap_: function() {
if (this.shortcut) {
this.pendingShortcut_ = '';
this.commitPending_();
}
},
});
return {ShortcutInput: ShortcutInput};
});