+<!DOCTYPE html>
<html>
<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>The source code</title>
- <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
- <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
+ <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
+ <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
+ <style type="text/css">
+ .highlight { display: block; background-color: #ddd; }
+ </style>
+ <script type="text/javascript">
+ function highlight() {
+ document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
+ }
+ </script>
</head>
-<body onload="prettyPrint();">
- <pre class="prettyprint lang-js">/*!
- * Ext JS Library 3.3.1
- * Copyright(c) 2006-2010 Sencha Inc.
- * licensing@sencha.com
- * http://www.sencha.com/license
- */
-<div id="cls-Ext.KeyMap"></div>/**
- * @class Ext.KeyMap
+<body onload="prettyPrint(); highlight();">
+ <pre class="prettyprint lang-js"><span id='Ext-util-KeyMap'>/**
+</span> * @class Ext.util.KeyMap
* Handles mapping keys to actions for an element. One key map can be used for multiple actions.
* The constructor accepts the same config object as defined by {@link #addBinding}.
* If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
* combination it will call the function with this signature (if the match is a multi-key
* combination the callback will still be called only once): (String key, Ext.EventObject e)
- * A KeyMap can also handle a string representation of keys.<br />
+ * A KeyMap can also handle a string representation of keys. By default KeyMap starts enabled.<br />
* Usage:
- <pre><code>
+ <pre><code>
// map one key by key code
-var map = new Ext.KeyMap("my-element", {
+var map = new Ext.util.KeyMap("my-element", {
key: 13, // or Ext.EventObject.ENTER
fn: myHandler,
scope: myObject
});
// map multiple keys to one action by string
-var map = new Ext.KeyMap("my-element", {
- key: "a\r\n\t",
+var map = new Ext.util.KeyMap("my-element", {
+ key: "a\r\n\t",
fn: myHandler,
scope: myObject
});
// map multiple keys to multiple actions by strings and array of codes
-var map = new Ext.KeyMap("my-element", [
+var map = new Ext.util.KeyMap("my-element", [
{
key: [10,13],
- fn: function(){ alert("Return was pressed"); }
+ fn: function(){ alert("Return was pressed"); }
}, {
- key: "abc",
+ key: "abc",
fn: function(){ alert('a, b or c was pressed'); }
}, {
- key: "\t",
+ key: "\t",
ctrl:true,
shift:true,
fn: function(){ alert('Control + shift + tab was pressed.'); }
}
]);
-</code></pre>
- * <b>Note: A KeyMap starts enabled</b>
- * @constructor
- * @param {Mixed} el The element to bind to
- * @param {Object} config The config (see {@link #addBinding})
- * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
+</code></pre>
*/
-Ext.KeyMap = function(el, config, eventName){
- this.el = Ext.get(el);
- this.eventName = eventName || "keydown";
- this.bindings = [];
- if(config){
- this.addBinding(config);
- }
- this.enable();
-};
-
-Ext.KeyMap.prototype = {
- <div id="prop-Ext.KeyMap-stopEvent"></div>/**
- * True to stop the event from bubbling and prevent the default browser action if the
- * key was handled by the KeyMap (defaults to false)
- * @type Boolean
+Ext.define('Ext.util.KeyMap', {
+ alternateClassName: 'Ext.KeyMap',
+
+<span id='Ext-util-KeyMap-method-constructor'> /**
+</span> * Creates new KeyMap.
+ * @param {String/HTMLElement/Ext.Element} el The element or its ID to bind to
+ * @param {Object} binding The binding (see {@link #addBinding})
+ * @param {String} [eventName="keydown"] The event to bind to
*/
- stopEvent : false,
-
- <div id="method-Ext.KeyMap-addBinding"></div>/**
- * Add a new binding to this KeyMap. The following config object properties are supported:
- * <pre>
-Property Type Description
----------- --------------- ----------------------------------------------------------------------
-key String/Array A single keycode or an array of keycodes to handle
-shift Boolean True to handle key only when shift is pressed, False to handle the key only when shift is not pressed (defaults to undefined)
-ctrl Boolean True to handle key only when ctrl is pressed, False to handle the key only when ctrl is not pressed (defaults to undefined)
-alt Boolean True to handle key only when alt is pressed, False to handle the key only when alt is not pressed (defaults to undefined)
-handler Function The function to call when KeyMap finds the expected key combination
-fn Function Alias of handler (for backwards-compatibility)
-scope Object The scope of the callback function
-stopEvent Boolean True to stop the event from bubbling and prevent the default browser action if the key was handled by the KeyMap (defaults to false)
-</pre>
+ constructor: function(el, binding, eventName){
+ var me = this;
+
+ Ext.apply(me, {
+ el: Ext.get(el),
+ eventName: eventName || me.eventName,
+ bindings: []
+ });
+ if (binding) {
+ me.addBinding(binding);
+ }
+ me.enable();
+ },
+
+ eventName: 'keydown',
+
+<span id='Ext-util-KeyMap-method-addBinding'> /**
+</span> * Add a new binding to this KeyMap. The following config object properties are supported:
+ * <pre>
+Property Type Description
+---------- --------------- ----------------------------------------------------------------------
+key String/Array A single keycode or an array of keycodes to handle
+shift Boolean True to handle key only when shift is pressed, False to handle the key only when shift is not pressed (defaults to undefined)
+ctrl Boolean True to handle key only when ctrl is pressed, False to handle the key only when ctrl is not pressed (defaults to undefined)
+alt Boolean True to handle key only when alt is pressed, False to handle the key only when alt is not pressed (defaults to undefined)
+handler Function The function to call when KeyMap finds the expected key combination
+fn Function Alias of handler (for backwards-compatibility)
+scope Object The scope of the callback function
+defaultEventAction String A default action to apply to the event. Possible values are: stopEvent, stopPropagation, preventDefault. If no value is set no action is performed.
+</pre>
*
* Usage:
- * <pre><code>
+ * <pre><code>
// Create a KeyMap
-var map = new Ext.KeyMap(document, {
+var map = new Ext.util.KeyMap(document, {
key: Ext.EventObject.ENTER,
fn: handleKey,
scope: this
fn: handleKey,
scope: this
});
-</code></pre>
- * @param {Object/Array} config A single KeyMap config or an array of configs
+</code></pre>
+ * @param {Object/Object[]} binding A single KeyMap config or an array of configs
*/
- addBinding : function(config){
- if(Ext.isArray(config)){
- Ext.each(config, function(c){
- this.addBinding(c);
- }, this);
+ addBinding : function(binding){
+ if (Ext.isArray(binding)) {
+ Ext.each(binding, this.addBinding, this);
return;
}
- var keyCode = config.key,
- fn = config.fn || config.handler,
- scope = config.scope;
-
- if (config.stopEvent) {
- this.stopEvent = config.stopEvent;
- }
-
- if(typeof keyCode == "string"){
- var ks = [];
- var keyString = keyCode.toUpperCase();
- for(var j = 0, len = keyString.length; j < len; j++){
- ks.push(keyString.charCodeAt(j));
+
+ var keyCode = binding.key,
+ processed = false,
+ key,
+ keys,
+ keyString,
+ i,
+ len;
+
+ if (Ext.isString(keyCode)) {
+ keys = [];
+ keyString = keyCode.toUpperCase();
+
+ for (i = 0, len = keyString.length; i < len; ++i){
+ keys.push(keyString.charCodeAt(i));
}
- keyCode = ks;
+ keyCode = keys;
+ processed = true;
}
- var keyArray = Ext.isArray(keyCode);
-
- var handler = function(e){
- if(this.checkModifiers(config, e)){
- var k = e.getKey();
- if(keyArray){
- for(var i = 0, len = keyCode.length; i < len; i++){
- if(keyCode[i] == k){
- if(this.stopEvent){
- e.stopEvent();
- }
- fn.call(scope || window, k, e);
- return;
- }
- }
- }else{
- if(k == keyCode){
- if(this.stopEvent){
- e.stopEvent();
- }
- fn.call(scope || window, k, e);
+
+ if (!Ext.isArray(keyCode)) {
+ keyCode = [keyCode];
+ }
+
+ if (!processed) {
+ for (i = 0, len = keyCode.length; i < len; ++i) {
+ key = keyCode[i];
+ if (Ext.isString(key)) {
+ keyCode[i] = key.toUpperCase().charCodeAt(0);
+ }
+ }
+ }
+
+ this.bindings.push(Ext.apply({
+ keyCode: keyCode
+ }, binding));
+ },
+
+<span id='Ext-util-KeyMap-method-handleKeyDown'> /**
+</span> * Process any keydown events on the element
+ * @private
+ * @param {Ext.EventObject} event
+ */
+ handleKeyDown: function(event) {
+ if (this.enabled) { //just in case
+ var bindings = this.bindings,
+ i = 0,
+ len = bindings.length;
+
+ event = this.processEvent(event);
+ for(; i < len; ++i){
+ this.processBinding(bindings[i], event);
+ }
+ }
+ },
+
+<span id='Ext-util-KeyMap-method-processEvent'> /**
+</span> * Ugly hack to allow this class to be tested. Currently WebKit gives
+ * no way to raise a key event properly with both
+ * a) A keycode
+ * b) The alt/ctrl/shift modifiers
+ * So we have to simulate them here. Yuk!
+ * This is a stub method intended to be overridden by tests.
+ * More info: https://bugs.webkit.org/show_bug.cgi?id=16735
+ * @private
+ */
+ processEvent: function(event){
+ return event;
+ },
+
+<span id='Ext-util-KeyMap-method-processBinding'> /**
+</span> * Process a particular binding and fire the handler if necessary.
+ * @private
+ * @param {Object} binding The binding information
+ * @param {Ext.EventObject} event
+ */
+ processBinding: function(binding, event){
+ if (this.checkModifiers(binding, event)) {
+ var key = event.getKey(),
+ handler = binding.fn || binding.handler,
+ scope = binding.scope || this,
+ keyCode = binding.keyCode,
+ defaultEventAction = binding.defaultEventAction,
+ i,
+ len,
+ keydownEvent = new Ext.EventObjectImpl(event);
+
+
+ for (i = 0, len = keyCode.length; i < len; ++i) {
+ if (key === keyCode[i]) {
+ if (handler.call(scope, key, event) !== true && defaultEventAction) {
+ keydownEvent[defaultEventAction]();
}
+ break;
}
}
- };
- this.bindings.push(handler);
- },
-
- // private
- checkModifiers: function(config, e){
- var val, key, keys = ['shift', 'ctrl', 'alt'];
- for (var i = 0, len = keys.length; i < len; ++i){
+ }
+ },
+
+<span id='Ext-util-KeyMap-method-checkModifiers'> /**
+</span> * Check if the modifiers on the event match those on the binding
+ * @private
+ * @param {Object} binding
+ * @param {Ext.EventObject} event
+ * @return {Boolean} True if the event matches the binding
+ */
+ checkModifiers: function(binding, e){
+ var keys = ['shift', 'ctrl', 'alt'],
+ i = 0,
+ len = keys.length,
+ val, key;
+
+ for (; i < len; ++i){
key = keys[i];
- val = config[key];
- if(!(val === undefined || (val === e[key + 'Key']))){
+ val = binding[key];
+ if (!(val === undefined || (val === e[key + 'Key']))) {
return false;
}
}
return true;
},
- <div id="method-Ext.KeyMap-on"></div>/**
- * Shorthand for adding a single key listener
- * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
+<span id='Ext-util-KeyMap-method-on'> /**
+</span> * Shorthand for adding a single key listener
+ * @param {Number/Number[]/Object} key Either the numeric key code, array of key codes or an object with the
* following options:
* {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
* @param {Function} fn The function to call
- * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the browser window.
+ * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the browser window.
*/
- on : function(key, fn, scope){
+ on: function(key, fn, scope) {
var keyCode, shift, ctrl, alt;
- if(typeof key == "object" && !Ext.isArray(key)){
+ if (Ext.isObject(key) && !Ext.isArray(key)) {
keyCode = key.key;
shift = key.shift;
ctrl = key.ctrl;
alt = key.alt;
- }else{
+ } else {
keyCode = key;
}
this.addBinding({
});
},
- // private
- handleKeyDown : function(e){
- if(this.enabled){ //just in case
- var b = this.bindings;
- for(var i = 0, len = b.length; i < len; i++){
- b[i].call(this, e);
- }
- }
- },
-
- <div id="method-Ext.KeyMap-isEnabled"></div>/**
- * Returns true if this KeyMap is enabled
- * @return {Boolean}
- */
- isEnabled : function(){
- return this.enabled;
- },
-
- <div id="method-Ext.KeyMap-enable"></div>/**
- * Enables this KeyMap
- */
- enable: function(){
- if(!this.enabled){
- this.el.on(this.eventName, this.handleKeyDown, this);
- this.enabled = true;
- }
- },
-
- <div id="method-Ext.KeyMap-disable"></div>/**
- * Disable this KeyMap
- */
- disable: function(){
- if(this.enabled){
- this.el.removeListener(this.eventName, this.handleKeyDown, this);
- this.enabled = false;
- }
- },
-
- <div id="method-Ext.KeyMap-setDisabled"></div>/**
- * Convenience function for setting disabled/enabled by boolean.
+<span id='Ext-util-KeyMap-method-isEnabled'> /**
+</span> * Returns true if this KeyMap is enabled
+ * @return {Boolean}
+ */
+ isEnabled : function(){
+ return this.enabled;
+ },
+
+<span id='Ext-util-KeyMap-method-enable'> /**
+</span> * Enables this KeyMap
+ */
+ enable: function(){
+ var me = this;
+
+ if (!me.enabled) {
+ me.el.on(me.eventName, me.handleKeyDown, me);
+ me.enabled = true;
+ }
+ },
+
+<span id='Ext-util-KeyMap-method-disable'> /**
+</span> * Disable this KeyMap
+ */
+ disable: function(){
+ var me = this;
+
+ if (me.enabled) {
+ me.el.removeListener(me.eventName, me.handleKeyDown, me);
+ me.enabled = false;
+ }
+ },
+
+<span id='Ext-util-KeyMap-method-setDisabled'> /**
+</span> * Convenience function for setting disabled/enabled by boolean.
* @param {Boolean} disabled
*/
setDisabled : function(disabled){
- this[disabled ? "disable" : "enable"]();
+ if (disabled) {
+ this.disable();
+ } else {
+ this.enable();
+ }
+ },
+
+<span id='Ext-util-KeyMap-method-destroy'> /**
+</span> * Destroys the KeyMap instance and removes all handlers.
+ * @param {Boolean} removeEl True to also remove the attached element
+ */
+ destroy: function(removeEl){
+ var me = this;
+
+ me.bindings = [];
+ me.disable();
+ if (removeEl === true) {
+ me.el.remove();
+ }
+ delete me.el;
}
-};</pre>
+});</pre>
</body>
-</html>
\ No newline at end of file
+</html>