view onlypaths/js/ext/keymap.js @ 61:14271eedf004 laserkard

[svn r62] saving for transference to cd
author rlm
date Fri, 19 Mar 2010 07:27:37 -0400
parents 26c2b3ad21c7
children
line wrap: on
line source
1 /**
2 * @class Ext.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.<br />
9 * Usage:
10 <pre><code>
11 // map one key by key code
12 var map = new Ext.KeyMap("my-element", {
13 key: 13, // or Ext.EventObject.ENTER
14 fn: myHandler,
15 scope: myObject
16 });
18 // map multiple keys to one action by string
19 var map = new Ext.KeyMap("my-element", {
20 key: "a\r\n\t",
21 fn: myHandler,
22 scope: myObject
23 });
25 // map multiple keys to multiple actions by strings and array of codes
26 var map = new Ext.KeyMap("my-element", [
27 {
28 key: [10,13],
29 fn: function(){ alert("Return was pressed"); }
30 }, {
31 key: "abc",
32 fn: function(){ alert('a, b or c was pressed'); }
33 }, {
34 key: "\t",
35 ctrl:true,
36 shift:true,
37 fn: function(){ alert('Control + shift + tab was pressed.'); }
38 }
39 ]);
40 </code></pre>
41 * <b>Note: A KeyMap starts enabled</b>
42 * @constructor
43 * @param {String/HTMLElement/Ext.Element} el The element to bind to
44 * @param {Object} config The config (see {@link #addBinding})
45 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
46 */
47 Ext.KeyMap = function(el, config, eventName){
48 this.el = Ext.get(el);
49 this.eventName = eventName || "keydown";
50 this.bindings = [];
51 if(config){
52 this.addBinding(config);
53 }
54 this.enable();
55 };
57 Ext.KeyMap.prototype = {
58 /**
59 * True to stop the event from bubbling and prevent the default browser action if the
60 * key was handled by the KeyMap (defaults to false)
61 * @type Boolean
62 */
63 stopEvent : false,
65 /**
66 * Add a new binding to this KeyMap. The following config object properties are supported:
67 * <pre>
68 Property Type Description
69 ---------- --------------- ----------------------------------------------------------------------
70 key String/Array A single keycode or an array of keycodes to handle
71 shift Boolean True to handle key only when shift is pressed (defaults to false)
72 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
73 alt Boolean True to handle key only when alt is pressed (defaults to false)
74 fn Function The function to call when KeyMap finds the expected key combination
75 scope Object The scope of the callback function
76 </pre>
77 *
78 * Usage:
79 * <pre><code>
80 // Create a KeyMap
81 var map = new Ext.KeyMap(document, {
82 key: Ext.EventObject.ENTER,
83 fn: handleKey,
84 scope: this
85 });
87 //Add a new binding to the existing KeyMap later
88 map.addBinding({
89 key: 'abc',
90 shift: true,
91 fn: handleKey,
92 scope: this
93 });
94 </code></pre>
95 * @param {Object/Array} config A single KeyMap config or an array of configs
96 */
97 addBinding : function(config){
98 if(config instanceof Array){
99 for(var i = 0, len = config.length; i < len; i++){
100 this.addBinding(config[i]);
101 }
102 return;
103 }
104 var keyCode = config.key,
105 shift = config.shift,
106 ctrl = config.ctrl,
107 alt = config.alt,
108 fn = config.fn,
109 scope = config.scope;
110 if(typeof keyCode == "string"){
111 var ks = [];
112 var keyString = keyCode.toUpperCase();
113 for(var j = 0, len = keyString.length; j < len; j++){
114 ks.push(keyString.charCodeAt(j));
115 }
116 keyCode = ks;
117 }
118 var keyArray = keyCode instanceof Array;
119 var handler = function(e){
120 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
121 var k = e.getKey();
122 if(keyArray){
123 for(var i = 0, len = keyCode.length; i < len; i++){
124 if(keyCode[i] == k){
125 if(this.stopEvent){
126 e.stopEvent();
127 }
128 fn.call(scope || window, k, e);
129 return;
130 }
131 }
132 }else{
133 if(k == keyCode){
134 if(this.stopEvent){
135 e.stopEvent();
136 }
137 fn.call(scope || window, k, e);
138 }
139 }
140 }
141 };
142 this.bindings.push(handler);
143 },
145 /**
146 * Shorthand for adding a single key listener
147 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
148 * following options:
149 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
150 * @param {Function} fn The function to call
151 * @param {Object} scope (optional) The scope of the function
152 */
153 on : function(key, fn, scope){
154 var keyCode, shift, ctrl, alt;
155 if(typeof key == "object" && !(key instanceof Array)){
156 keyCode = key.key;
157 shift = key.shift;
158 ctrl = key.ctrl;
159 alt = key.alt;
160 }else{
161 keyCode = key;
162 }
163 this.addBinding({
164 key: keyCode,
165 shift: shift,
166 ctrl: ctrl,
167 alt: alt,
168 fn: fn,
169 scope: scope
170 })
171 },
173 // private
174 handleKeyDown : function(e){
175 if(this.enabled){ //just in case
176 var b = this.bindings;
177 for(var i = 0, len = b.length; i < len; i++){
178 b[i].call(this, e);
179 }
180 }
181 },
183 /**
184 * Returns true if this KeyMap is enabled
185 * @return {Boolean}
186 */
187 isEnabled : function(){
188 return this.enabled;
189 },
191 /**
192 * Enables this KeyMap
193 */
194 enable: function(){
195 if(!this.enabled){
196 this.el.on(this.eventName, this.handleKeyDown, this);
197 this.enabled = true;
198 }
199 },
201 /**
202 * Disable this KeyMap
203 */
204 disable: function(){
205 if(this.enabled){
206 this.el.removeListener(this.eventName, this.handleKeyDown, this);
207 this.enabled = false;
208 }
209 }
210 };