diff onlypaths/js/ext/keymap.js @ 46:26c2b3ad21c7 laserkard

[svn r47] saving progresswww.cinemassacre.com/new/?page_id=30
author rlm
date Sun, 31 Jan 2010 12:33:33 -0500
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/onlypaths/js/ext/keymap.js	Sun Jan 31 12:33:33 2010 -0500
     1.3 @@ -0,0 +1,210 @@
     1.4 +/**
     1.5 + * @class Ext.KeyMap
     1.6 + * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
     1.7 + * The constructor accepts the same config object as defined by {@link #addBinding}.
     1.8 + * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
     1.9 + * combination it will call the function with this signature (if the match is a multi-key
    1.10 + * combination the callback will still be called only once): (String key, Ext.EventObject e)
    1.11 + * A KeyMap can also handle a string representation of keys.<br />
    1.12 + * Usage:
    1.13 + <pre><code>
    1.14 +// map one key by key code
    1.15 +var map = new Ext.KeyMap("my-element", {
    1.16 +    key: 13, // or Ext.EventObject.ENTER
    1.17 +    fn: myHandler,
    1.18 +    scope: myObject
    1.19 +});
    1.20 +
    1.21 +// map multiple keys to one action by string
    1.22 +var map = new Ext.KeyMap("my-element", {
    1.23 +    key: "a\r\n\t",
    1.24 +    fn: myHandler,
    1.25 +    scope: myObject
    1.26 +});
    1.27 +
    1.28 +// map multiple keys to multiple actions by strings and array of codes
    1.29 +var map = new Ext.KeyMap("my-element", [
    1.30 +    {
    1.31 +        key: [10,13],
    1.32 +        fn: function(){ alert("Return was pressed"); }
    1.33 +    }, {
    1.34 +        key: "abc",
    1.35 +        fn: function(){ alert('a, b or c was pressed'); }
    1.36 +    }, {
    1.37 +        key: "\t",
    1.38 +        ctrl:true,
    1.39 +        shift:true,
    1.40 +        fn: function(){ alert('Control + shift + tab was pressed.'); }
    1.41 +    }
    1.42 +]);
    1.43 +</code></pre>
    1.44 + * <b>Note: A KeyMap starts enabled</b>
    1.45 + * @constructor
    1.46 + * @param {String/HTMLElement/Ext.Element} el The element to bind to
    1.47 + * @param {Object} config The config (see {@link #addBinding})
    1.48 + * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
    1.49 + */
    1.50 +Ext.KeyMap = function(el, config, eventName){
    1.51 +    this.el  = Ext.get(el);
    1.52 +    this.eventName = eventName || "keydown";
    1.53 +    this.bindings = [];
    1.54 +    if(config){
    1.55 +        this.addBinding(config);
    1.56 +    }
    1.57 +    this.enable();
    1.58 +};
    1.59 +
    1.60 +Ext.KeyMap.prototype = {
    1.61 +    /**
    1.62 +     * True to stop the event from bubbling and prevent the default browser action if the
    1.63 +     * key was handled by the KeyMap (defaults to false)
    1.64 +     * @type Boolean
    1.65 +     */
    1.66 +    stopEvent : false,
    1.67 +
    1.68 +    /**
    1.69 +     * Add a new binding to this KeyMap. The following config object properties are supported:
    1.70 +     * <pre>
    1.71 +Property    Type             Description
    1.72 +----------  ---------------  ----------------------------------------------------------------------
    1.73 +key         String/Array     A single keycode or an array of keycodes to handle
    1.74 +shift       Boolean          True to handle key only when shift is pressed (defaults to false)
    1.75 +ctrl        Boolean          True to handle key only when ctrl is pressed (defaults to false)
    1.76 +alt         Boolean          True to handle key only when alt is pressed (defaults to false)
    1.77 +fn          Function         The function to call when KeyMap finds the expected key combination
    1.78 +scope       Object           The scope of the callback function
    1.79 +</pre>
    1.80 +     *
    1.81 +     * Usage:
    1.82 +     * <pre><code>
    1.83 +// Create a KeyMap
    1.84 +var map = new Ext.KeyMap(document, {
    1.85 +    key: Ext.EventObject.ENTER,
    1.86 +    fn: handleKey,
    1.87 +    scope: this
    1.88 +});
    1.89 +
    1.90 +//Add a new binding to the existing KeyMap later
    1.91 +map.addBinding({
    1.92 +    key: 'abc',
    1.93 +    shift: true,
    1.94 +    fn: handleKey,
    1.95 +    scope: this
    1.96 +});
    1.97 +</code></pre>
    1.98 +     * @param {Object/Array} config A single KeyMap config or an array of configs
    1.99 +     */
   1.100 +	addBinding : function(config){
   1.101 +        if(config instanceof Array){
   1.102 +            for(var i = 0, len = config.length; i < len; i++){
   1.103 +                this.addBinding(config[i]);
   1.104 +            }
   1.105 +            return;
   1.106 +        }
   1.107 +        var keyCode = config.key,
   1.108 +            shift = config.shift, 
   1.109 +            ctrl = config.ctrl, 
   1.110 +            alt = config.alt,
   1.111 +            fn = config.fn,
   1.112 +            scope = config.scope;
   1.113 +        if(typeof keyCode == "string"){
   1.114 +            var ks = [];
   1.115 +            var keyString = keyCode.toUpperCase();
   1.116 +            for(var j = 0, len = keyString.length; j < len; j++){
   1.117 +                ks.push(keyString.charCodeAt(j));
   1.118 +            }
   1.119 +            keyCode = ks;
   1.120 +        }
   1.121 +        var keyArray = keyCode instanceof Array;
   1.122 +        var handler = function(e){
   1.123 +            if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) &&  (!alt || e.altKey)){
   1.124 +                var k = e.getKey();
   1.125 +                if(keyArray){
   1.126 +                    for(var i = 0, len = keyCode.length; i < len; i++){
   1.127 +                        if(keyCode[i] == k){
   1.128 +                          if(this.stopEvent){
   1.129 +                              e.stopEvent();
   1.130 +                          }
   1.131 +                          fn.call(scope || window, k, e);
   1.132 +                          return;
   1.133 +                        }
   1.134 +                    }
   1.135 +                }else{
   1.136 +                    if(k == keyCode){
   1.137 +                        if(this.stopEvent){
   1.138 +                           e.stopEvent();
   1.139 +                        }
   1.140 +                        fn.call(scope || window, k, e);
   1.141 +                    }
   1.142 +                }
   1.143 +            }
   1.144 +        };
   1.145 +        this.bindings.push(handler);  
   1.146 +	},
   1.147 +
   1.148 +    /**
   1.149 +     * Shorthand for adding a single key listener
   1.150 +     * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
   1.151 +     * following options:
   1.152 +     * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
   1.153 +     * @param {Function} fn The function to call
   1.154 +     * @param {Object} scope (optional) The scope of the function
   1.155 +     */
   1.156 +    on : function(key, fn, scope){
   1.157 +        var keyCode, shift, ctrl, alt;
   1.158 +        if(typeof key == "object" && !(key instanceof Array)){
   1.159 +            keyCode = key.key;
   1.160 +            shift = key.shift;
   1.161 +            ctrl = key.ctrl;
   1.162 +            alt = key.alt;
   1.163 +        }else{
   1.164 +            keyCode = key;
   1.165 +        }
   1.166 +        this.addBinding({
   1.167 +            key: keyCode,
   1.168 +            shift: shift,
   1.169 +            ctrl: ctrl,
   1.170 +            alt: alt,
   1.171 +            fn: fn,
   1.172 +            scope: scope
   1.173 +        })
   1.174 +    },
   1.175 +
   1.176 +    // private
   1.177 +    handleKeyDown : function(e){
   1.178 +	    if(this.enabled){ //just in case
   1.179 +    	    var b = this.bindings;
   1.180 +    	    for(var i = 0, len = b.length; i < len; i++){
   1.181 +    	        b[i].call(this, e);
   1.182 +    	    }
   1.183 +	    }
   1.184 +	},
   1.185 +	
   1.186 +	/**
   1.187 +	 * Returns true if this KeyMap is enabled
   1.188 +	 * @return {Boolean} 
   1.189 +	 */
   1.190 +	isEnabled : function(){
   1.191 +	    return this.enabled;  
   1.192 +	},
   1.193 +	
   1.194 +	/**
   1.195 +	 * Enables this KeyMap
   1.196 +	 */
   1.197 +	enable: function(){
   1.198 +		if(!this.enabled){
   1.199 +		    this.el.on(this.eventName, this.handleKeyDown, this);
   1.200 +		    this.enabled = true;
   1.201 +		}
   1.202 +	},
   1.203 +
   1.204 +	/**
   1.205 +	 * Disable this KeyMap
   1.206 +	 */
   1.207 +	disable: function(){
   1.208 +		if(this.enabled){
   1.209 +		    this.el.removeListener(this.eventName, this.handleKeyDown, this);
   1.210 +		    this.enabled = false;
   1.211 +		}
   1.212 +	}
   1.213 +};
   1.214 \ No newline at end of file