Mercurial > laserkard
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