X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/ee06f37b0f6f6d94cd05a6ffae556660f7c4a2bc..c930e9176a5a85509c5b0230e2bff5c22a591432:/src/util/KeyMap.js?ds=sidebyside
diff --git a/src/util/KeyMap.js b/src/util/KeyMap.js
new file mode 100644
index 00000000..c13a64a6
--- /dev/null
+++ b/src/util/KeyMap.js
@@ -0,0 +1,242 @@
+/*!
+ * Ext JS Library 3.0.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+/**
+ * @class Ext.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.
+ * Usage:
+
+// map one key by key code
+var map = new Ext.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",
+ fn: myHandler,
+ scope: myObject
+});
+
+// map multiple keys to multiple actions by strings and array of codes
+var map = new Ext.KeyMap("my-element", [
+ {
+ key: [10,13],
+ fn: function(){ alert("Return was pressed"); }
+ }, {
+ key: "abc",
+ fn: function(){ alert('a, b or c was pressed'); }
+ }, {
+ key: "\t",
+ ctrl:true,
+ shift:true,
+ fn: function(){ alert('Control + shift + tab was pressed.'); }
+ }
+]);
+
+ * Note: A KeyMap starts enabled
+ * @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")
+ */
+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 = {
+ /**
+ * 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
+ */
+ stopEvent : false,
+
+ /**
+ * Add a new binding to this KeyMap. The following config object properties are supported:
+ * +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) ++ * + * Usage: + *
+// Create a KeyMap
+var map = new Ext.KeyMap(document, {
+ key: Ext.EventObject.ENTER,
+ fn: handleKey,
+ scope: this
+});
+
+//Add a new binding to the existing KeyMap later
+map.addBinding({
+ key: 'abc',
+ shift: true,
+ fn: handleKey,
+ scope: this
+});
+
+ * @param {Object/Array} config 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);
+ 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));
+ }
+ keyCode = ks;
+ }
+ 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);
+ }
+ }
+ }
+ };
+ 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){
+ key = keys[i];
+ val = config[key];
+ if(!(val === undefined || (val === e[key + 'Key']))){
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /**
+ * 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
+ * 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 of the function
+ */
+ on : function(key, fn, scope){
+ var keyCode, shift, ctrl, alt;
+ if(typeof key == "object" && !Ext.isArray(key)){
+ keyCode = key.key;
+ shift = key.shift;
+ ctrl = key.ctrl;
+ alt = key.alt;
+ }else{
+ keyCode = key;
+ }
+ this.addBinding({
+ key: keyCode,
+ shift: shift,
+ ctrl: ctrl,
+ alt: alt,
+ fn: fn,
+ scope: scope
+ });
+ },
+
+ // 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);
+ }
+ }
+ },
+
+ /**
+ * Returns true if this KeyMap is enabled
+ * @return {Boolean}
+ */
+ isEnabled : function(){
+ return this.enabled;
+ },
+
+ /**
+ * Enables this KeyMap
+ */
+ enable: function(){
+ if(!this.enabled){
+ this.el.on(this.eventName, this.handleKeyDown, this);
+ this.enabled = true;
+ }
+ },
+
+ /**
+ * Disable this KeyMap
+ */
+ disable: function(){
+ if(this.enabled){
+ this.el.removeListener(this.eventName, this.handleKeyDown, this);
+ this.enabled = false;
+ }
+ },
+
+ /**
+ * Convenience function for setting disabled/enabled by boolean.
+ * @param {Boolean} disabled
+ */
+ setDisabled : function(disabled){
+ this[disabled ? "disable" : "enable"]();
+ }
+};
\ No newline at end of file