~cdparra/gelee/trunk

« back to all changes in this revision

Viewing changes to webui/web/extjs/source/util/KeyMap.js

  • Committer: parra
  • Date: 2010-03-15 15:56:56 UTC
  • Revision ID: svn-v4:ac5bba68-f036-4e09-846e-8f32731cc928:trunk/gelee:1448
merged gelee at svn

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Ext JS Library 3.0 RC2
 
3
 * Copyright(c) 2006-2009, Ext JS, LLC.
 
4
 * licensing@extjs.com
 
5
 * 
 
6
 * http://extjs.com/license
 
7
 */
 
8
 
 
9
/**
 
10
 * @class Ext.KeyMap
 
11
 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
 
12
 * The constructor accepts the same config object as defined by {@link #addBinding}.
 
13
 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
 
14
 * combination it will call the function with this signature (if the match is a multi-key
 
15
 * combination the callback will still be called only once): (String key, Ext.EventObject e)
 
16
 * A KeyMap can also handle a string representation of keys.<br />
 
17
 * Usage:
 
18
 <pre><code>
 
19
// map one key by key code
 
20
var map = new Ext.KeyMap("my-element", {
 
21
    key: 13, // or Ext.EventObject.ENTER
 
22
    fn: myHandler,
 
23
    scope: myObject
 
24
});
 
25
 
 
26
// map multiple keys to one action by string
 
27
var map = new Ext.KeyMap("my-element", {
 
28
    key: "a\r\n\t",
 
29
    fn: myHandler,
 
30
    scope: myObject
 
31
});
 
32
 
 
33
// map multiple keys to multiple actions by strings and array of codes
 
34
var map = new Ext.KeyMap("my-element", [
 
35
    {
 
36
        key: [10,13],
 
37
        fn: function(){ alert("Return was pressed"); }
 
38
    }, {
 
39
        key: "abc",
 
40
        fn: function(){ alert('a, b or c was pressed'); }
 
41
    }, {
 
42
        key: "\t",
 
43
        ctrl:true,
 
44
        shift:true,
 
45
        fn: function(){ alert('Control + shift + tab was pressed.'); }
 
46
    }
 
47
]);
 
48
</code></pre>
 
49
 * <b>Note: A KeyMap starts enabled</b>
 
50
 * @constructor
 
51
 * @param {Mixed} el The element to bind to
 
52
 * @param {Object} config The config (see {@link #addBinding})
 
53
 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
 
54
 */
 
55
Ext.KeyMap = function(el, config, eventName){
 
56
    this.el  = Ext.get(el);
 
57
    this.eventName = eventName || "keydown";
 
58
    this.bindings = [];
 
59
    if(config){
 
60
        this.addBinding(config);
 
61
    }
 
62
    this.enable();
 
63
};
 
64
 
 
65
Ext.KeyMap.prototype = {
 
66
    /**
 
67
     * True to stop the event from bubbling and prevent the default browser action if the
 
68
     * key was handled by the KeyMap (defaults to false)
 
69
     * @type Boolean
 
70
     */
 
71
    stopEvent : false,
 
72
 
 
73
    /**
 
74
     * Add a new binding to this KeyMap. The following config object properties are supported:
 
75
     * <pre>
 
76
Property    Type             Description
 
77
----------  ---------------  ----------------------------------------------------------------------
 
78
key         String/Array     A single keycode or an array of keycodes to handle
 
79
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)
 
80
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)
 
81
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)
 
82
handler     Function         The function to call when KeyMap finds the expected key combination
 
83
fn          Function         Alias of handler (for backwards-compatibility)
 
84
scope       Object           The scope of the callback function
 
85
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)
 
86
</pre>
 
87
     *
 
88
     * Usage:
 
89
     * <pre><code>
 
90
// Create a KeyMap
 
91
var map = new Ext.KeyMap(document, {
 
92
    key: Ext.EventObject.ENTER,
 
93
    fn: handleKey,
 
94
    scope: this
 
95
});
 
96
 
 
97
//Add a new binding to the existing KeyMap later
 
98
map.addBinding({
 
99
    key: 'abc',
 
100
    shift: true,
 
101
    fn: handleKey,
 
102
    scope: this
 
103
});
 
104
</code></pre>
 
105
     * @param {Object/Array} config A single KeyMap config or an array of configs
 
106
     */
 
107
        addBinding : function(config){
 
108
        if(Ext.isArray(config)){
 
109
            for(var i = 0, len = config.length; i < len; i++){
 
110
                this.addBinding(config[i]);
 
111
            }
 
112
            return;
 
113
        }
 
114
        var keyCode = config.key,
 
115
            fn = config.fn || config.handler,
 
116
            scope = config.scope;
 
117
 
 
118
        if (config.stopEvent) {
 
119
            this.stopEvent = config.stopEvent;    
 
120
        }       
 
121
 
 
122
        if(typeof keyCode == "string"){
 
123
            var ks = [];
 
124
            var keyString = keyCode.toUpperCase();
 
125
            for(var j = 0, len = keyString.length; j < len; j++){
 
126
                ks.push(keyString.charCodeAt(j));
 
127
            }
 
128
            keyCode = ks;
 
129
        }
 
130
        var keyArray = Ext.isArray(keyCode);
 
131
        
 
132
        var handler = function(e){
 
133
            if(this.checkModifiers(config, e)){
 
134
                var k = e.getKey();
 
135
                if(keyArray){
 
136
                    for(var i = 0, len = keyCode.length; i < len; i++){
 
137
                        if(keyCode[i] == k){
 
138
                          if(this.stopEvent){
 
139
                              e.stopEvent();
 
140
                          }
 
141
                          fn.call(scope || window, k, e);
 
142
                          return;
 
143
                        }
 
144
                    }
 
145
                }else{
 
146
                    if(k == keyCode){
 
147
                        if(this.stopEvent){
 
148
                           e.stopEvent();
 
149
                        }
 
150
                        fn.call(scope || window, k, e);
 
151
                    }
 
152
                }
 
153
            }
 
154
        };
 
155
        this.bindings.push(handler);
 
156
        },
 
157
    
 
158
    // private
 
159
    checkModifiers: function(config, e){
 
160
        var val, key, keys = ['shift', 'ctrl', 'alt'];
 
161
        for (var i = 0, len = keys.length; i < len; ++i){
 
162
            key = keys[i], val = config[key];
 
163
            if(!(val === undefined || (val === e[key + 'Key']))){
 
164
                return false;
 
165
            }
 
166
        }
 
167
        return true;
 
168
    },
 
169
 
 
170
    /**
 
171
     * Shorthand for adding a single key listener
 
172
     * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
 
173
     * following options:
 
174
     * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
 
175
     * @param {Function} fn The function to call
 
176
     * @param {Object} scope (optional) The scope of the function
 
177
     */
 
178
    on : function(key, fn, scope){
 
179
        var keyCode, shift, ctrl, alt;
 
180
        if(typeof key == "object" && !Ext.isArray(key)){
 
181
            keyCode = key.key;
 
182
            shift = key.shift;
 
183
            ctrl = key.ctrl;
 
184
            alt = key.alt;
 
185
        }else{
 
186
            keyCode = key;
 
187
        }
 
188
        this.addBinding({
 
189
            key: keyCode,
 
190
            shift: shift,
 
191
            ctrl: ctrl,
 
192
            alt: alt,
 
193
            fn: fn,
 
194
            scope: scope
 
195
        })
 
196
    },
 
197
 
 
198
    // private
 
199
    handleKeyDown : function(e){
 
200
            if(this.enabled){ //just in case
 
201
            var b = this.bindings;
 
202
            for(var i = 0, len = b.length; i < len; i++){
 
203
                b[i].call(this, e);
 
204
            }
 
205
            }
 
206
        },
 
207
 
 
208
        /**
 
209
         * Returns true if this KeyMap is enabled
 
210
         * @return {Boolean}
 
211
         */
 
212
        isEnabled : function(){
 
213
            return this.enabled;
 
214
        },
 
215
 
 
216
        /**
 
217
         * Enables this KeyMap
 
218
         */
 
219
        enable: function(){
 
220
                if(!this.enabled){
 
221
                    this.el.on(this.eventName, this.handleKeyDown, this);
 
222
                    this.enabled = true;
 
223
                }
 
224
        },
 
225
 
 
226
        /**
 
227
         * Disable this KeyMap
 
228
         */
 
229
        disable: function(){
 
230
                if(this.enabled){
 
231
                    this.el.removeListener(this.eventName, this.handleKeyDown, this);
 
232
                    this.enabled = false;
 
233
                }
 
234
        },
 
235
    
 
236
    /**
 
237
     * Convenience function for setting disabled/enabled by boolean.
 
238
     * @param {Boolean} disabled
 
239
     */
 
240
    setDisabled : function(disabled){
 
241
        this[disabled ? "disable" : "enable"]();
 
242
    }
 
243
};
 
 
b'\\ No newline at end of file'