Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / KeyMap.html
1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-util.KeyMap-method-constructor'><span id='Ext-util.KeyMap'>/**
2 </span></span> * @class Ext.util.KeyMap
3  * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
4  * The constructor accepts the same config object as defined by {@link #addBinding}.
5  * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
6  * combination it will call the function with this signature (if the match is a multi-key
7  * combination the callback will still be called only once): (String key, Ext.EventObject e)
8  * A KeyMap can also handle a string representation of keys.&lt;br /&gt;
9  * Usage:
10  &lt;pre&gt;&lt;code&gt;
11 // map one key by key code
12 var map = new Ext.util.KeyMap(&quot;my-element&quot;, {
13     key: 13, // or Ext.EventObject.ENTER
14     fn: myHandler,
15     scope: myObject
16 });
17
18 // map multiple keys to one action by string
19 var map = new Ext.util.KeyMap(&quot;my-element&quot;, {
20     key: &quot;a\r\n\t&quot;,
21     fn: myHandler,
22     scope: myObject
23 });
24
25 // map multiple keys to multiple actions by strings and array of codes
26 var map = new Ext.util.KeyMap(&quot;my-element&quot;, [
27     {
28         key: [10,13],
29         fn: function(){ alert(&quot;Return was pressed&quot;); }
30     }, {
31         key: &quot;abc&quot;,
32         fn: function(){ alert('a, b or c was pressed'); }
33     }, {
34         key: &quot;\t&quot;,
35         ctrl:true,
36         shift:true,
37         fn: function(){ alert('Control + shift + tab was pressed.'); }
38     }
39 ]);
40 &lt;/code&gt;&lt;/pre&gt;
41  * &lt;b&gt;Note: A KeyMap starts enabled&lt;/b&gt;
42  * @constructor
43  * @param {Mixed} el The element to bind to
44  * @param {Object} binding The binding (see {@link #addBinding})
45  * @param {String} eventName (optional) The event to bind to (defaults to &quot;keydown&quot;)
46  */
47 Ext.define('Ext.util.KeyMap', {
48     alternateClassName: 'Ext.KeyMap',
49     
50     constructor: function(el, binding, eventName){
51         var me = this;
52         
53         Ext.apply(me, {
54             el: Ext.get(el),
55             eventName: eventName || me.eventName,
56             bindings: []
57         });
58         if (binding) {
59             me.addBinding(binding);
60         }
61         me.enable();
62     },
63     
64     eventName: 'keydown',
65
66 <span id='Ext-util.KeyMap-method-addBinding'>    /**
67 </span>     * Add a new binding to this KeyMap. The following config object properties are supported:
68      * &lt;pre&gt;
69 Property            Type             Description
70 ----------          ---------------  ----------------------------------------------------------------------
71 key                 String/Array     A single keycode or an array of keycodes to handle
72 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)
73 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)
74 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)
75 handler             Function         The function to call when KeyMap finds the expected key combination
76 fn                  Function         Alias of handler (for backwards-compatibility)
77 scope               Object           The scope of the callback function
78 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. 
79 &lt;/pre&gt;
80      *
81      * Usage:
82      * &lt;pre&gt;&lt;code&gt;
83 // Create a KeyMap
84 var map = new Ext.util.KeyMap(document, {
85     key: Ext.EventObject.ENTER,
86     fn: handleKey,
87     scope: this
88 });
89
90 //Add a new binding to the existing KeyMap later
91 map.addBinding({
92     key: 'abc',
93     shift: true,
94     fn: handleKey,
95     scope: this
96 });
97 &lt;/code&gt;&lt;/pre&gt;
98      * @param {Object/Array} binding A single KeyMap config or an array of configs
99      */
100     addBinding : function(binding){
101         if (Ext.isArray(binding)) {
102             Ext.each(binding, this.addBinding, this);
103             return;
104         }
105         
106         var keyCode = binding.key,
107             processed = false,
108             key,
109             keys,
110             keyString,
111             i,
112             len;
113
114         if (Ext.isString(keyCode)) {
115             keys = [];
116             keyString = keyCode.toLowerCase();
117             
118             for (i = 0, len = keyString.length; i &lt; len; ++i){
119                 keys.push(keyString.charCodeAt(i));
120             }
121             keyCode = keys;
122             processed = true;
123         }
124         
125         if (!Ext.isArray(keyCode)) {
126             keyCode = [keyCode];
127         }
128         
129         if (!processed) {
130             for (i = 0, len = keyCode.length; i &lt; len; ++i) {
131                 key = keyCode[i];
132                 if (Ext.isString(key)) {
133                     keyCode[i] = key.toLowerCase().charCodeAt(0);
134                 }
135             }
136         }
137         
138         this.bindings.push(Ext.apply({
139             keyCode: keyCode
140         }, binding));
141     },
142     
143 <span id='Ext-util.KeyMap-method-handleKeyDown'>    /**
144 </span>     * Process any keydown events on the element
145      * @private
146      * @param {Ext.EventObject} event
147      */
148     handleKeyDown: function(event) {
149         if (this.enabled) { //just in case
150             var bindings = this.bindings,
151                 i = 0,
152                 len = bindings.length;
153                 
154             event = this.processEvent(event);
155             for(; i &lt; len; ++i){
156                 this.processBinding(bindings[i], event);
157             }
158         }
159     },
160     
161 <span id='Ext-util.KeyMap-method-processEvent'>    /**
162 </span>     * Ugly hack to allow this class to be tested. Currently WebKit gives
163      * no way to raise a key event properly with both
164      * a) A keycode
165      * b) The alt/ctrl/shift modifiers
166      * So we have to simulate them here. Yuk! 
167      * This is a stub method intended to be overridden by tests.
168      * More info: https://bugs.webkit.org/show_bug.cgi?id=16735
169      * @private
170      */
171     processEvent: function(event){
172         return event;
173     },
174     
175 <span id='Ext-util.KeyMap-method-processBinding'>    /**
176 </span>     * Process a particular binding and fire the handler if necessary.
177      * @private
178      * @param {Object} binding The binding information
179      * @param {Ext.EventObject} event
180      */
181     processBinding: function(binding, event){
182         if (this.checkModifiers(binding, event)) {
183             var key = event.getKey(),
184                 handler = binding.fn || binding.handler,
185                 scope = binding.scope || this,
186                 keyCode = binding.keyCode,
187                 defaultEventAction = binding.defaultEventAction,
188                 i,
189                 len,
190                 keydownEvent = new Ext.EventObjectImpl(event);
191                 
192             
193             for (i = 0, len = keyCode.length; i &lt; len; ++i) {
194                 if (key === keyCode[i]) {
195                     if (handler.call(scope, key, event) !== true &amp;&amp; defaultEventAction) {
196                         keydownEvent[defaultEventAction]();
197                     }
198                     break;
199                 }
200             }
201         }
202     },
203     
204 <span id='Ext-util.KeyMap-method-checkModifiers'>    /**
205 </span>     * Check if the modifiers on the event match those on the binding
206      * @private
207      * @param {Object} binding
208      * @param {Ext.EventObject} event
209      * @return {Boolean} True if the event matches the binding
210      */
211     checkModifiers: function(binding, e){
212         var keys = ['shift', 'ctrl', 'alt'],
213             i = 0,
214             len = keys.length,
215             val, key;
216             
217         for (; i &lt; len; ++i){
218             key = keys[i];
219             val = binding[key];
220             if (!(val === undefined || (val === e[key + 'Key']))) {
221                 return false;
222             }
223         }
224         return true;
225     },
226
227 <span id='Ext-util.KeyMap-method-on'>    /**
228 </span>     * Shorthand for adding a single key listener
229      * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
230      * following options:
231      * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
232      * @param {Function} fn The function to call
233      * @param {Object} scope (optional) The scope (&lt;code&gt;this&lt;/code&gt; reference) in which the function is executed. Defaults to the browser window.
234      */
235     on: function(key, fn, scope) {
236         var keyCode, shift, ctrl, alt;
237         if (Ext.isObject(key) &amp;&amp; !Ext.isArray(key)) {
238             keyCode = key.key;
239             shift = key.shift;
240             ctrl = key.ctrl;
241             alt = key.alt;
242         } else {
243             keyCode = key;
244         }
245         this.addBinding({
246             key: keyCode,
247             shift: shift,
248             ctrl: ctrl,
249             alt: alt,
250             fn: fn,
251             scope: scope
252         });
253     },
254
255 <span id='Ext-util.KeyMap-method-isEnabled'>    /**
256 </span>     * Returns true if this KeyMap is enabled
257      * @return {Boolean}
258      */
259     isEnabled : function(){
260         return this.enabled;
261     },
262
263 <span id='Ext-util.KeyMap-method-enable'>    /**
264 </span>     * Enables this KeyMap
265      */
266     enable: function(){
267         if(!this.enabled){
268             this.el.on(this.eventName, this.handleKeyDown, this);
269             this.enabled = true;
270         }
271     },
272
273 <span id='Ext-util.KeyMap-method-disable'>    /**
274 </span>     * Disable this KeyMap
275      */
276     disable: function(){
277         if(this.enabled){
278             this.el.removeListener(this.eventName, this.handleKeyDown, this);
279             this.enabled = false;
280         }
281     },
282
283 <span id='Ext-util.KeyMap-method-setDisabled'>    /**
284 </span>     * Convenience function for setting disabled/enabled by boolean.
285      * @param {Boolean} disabled
286      */
287     setDisabled : function(disabled){
288         if (disabled) {
289             this.disable();
290         } else {
291             this.enable();
292         }
293     },
294     
295 <span id='Ext-util.KeyMap-method-destroy'>    /**
296 </span>     * Destroys the KeyMap instance and removes all handlers.
297      * @param {Boolean} removeEl True to also remove the attached element
298      */
299     destroy: function(removeEl){
300         var me = this;
301         
302         me.bindings = [];
303         me.disable();
304         if (removeEl === true) {
305             me.el.remove();
306         }
307         delete me.el;
308     }
309 });</pre></pre></body></html>