1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 /**
 28  * android back button
 29  * @deprecated These were for android devices, but does not work in html5 environment
 30  * @constant
 31  * @type Number
 32  */
 33 cc.TYPE_BACK_CLICKED = 1;
 34 /**
 35  * android menu button
 36  * @deprecated for android devices, does not work in html5 environment
 37  * @constant
 38  * @type Number
 39  */
 40 cc.TYPE_MENU_CLICKED = 2;
 41 /**
 42  * keymap
 43  * @example
 44  * //Example
 45  * //to mark a keydown
 46  * cc.keyDown[65] = true;
 47  * //or
 48  * cc.keyMap[cc.KEY.a]
 49  *
 50  * //to mark a keyup
 51  * do cc.keyDown[65] = false;
 52  *
 53  * //to find out if a key is down, check
 54  * if(cc.keyDown[65])
 55  * //or
 56  * if,(cc.keyDown[cc.KEY.space])
 57  * //if its undefined or false or null, its not pressed
 58  * @constant
 59  * @type object
 60  */
 61 cc.KEY = {
 62     backspace:8,
 63     tab:9,
 64     enter:13,
 65     shift:16, //should use shiftkey instead
 66     ctrl:17, //should use ctrlkey
 67     alt:18, //should use altkey
 68     pause:19,
 69     capslock:20,
 70     escape:27,
 71     pageup:33,
 72     pagedown:34,
 73     end:35,
 74     home:36,
 75     left:37,
 76     up:38,
 77     right:39,
 78     down:40,
 79     insert:45,
 80     Delete:46,
 81     0:48,
 82     1:49,
 83     2:50,
 84     3:51,
 85     4:52,
 86     5:53,
 87     6:54,
 88     7:55,
 89     8:56,
 90     9:57,
 91     a:65,
 92     b:66,
 93     c:67,
 94     d:68,
 95     e:69,
 96     f:70,
 97     g:71,
 98     h:72,
 99     i:73,
100     j:74,
101     k:75,
102     l:76,
103     m:77,
104     n:78,
105     o:79,
106     p:80,
107     q:81,
108     r:82,
109     s:83,
110     t:84,
111     u:85,
112     v:86,
113     w:87,
114     x:88,
115     y:89,
116     z:90,
117     num0:96,
118     num1:97,
119     num2:98,
120     num3:99,
121     num4:100,
122     num5:101,
123     num6:102,
124     num7:103,
125     num8:104,
126     num9:105,
127     '*':106,
128     '+':107,
129     '-':109,
130     'numdel':110,
131     '/':111,
132     f1:112, //f1-f12 dont work on ie
133     f2:113,
134     f3:114,
135     f4:115,
136     f5:116,
137     f6:117,
138     f7:118,
139     f8:119,
140     f9:120,
141     f10:121,
142     f11:122,
143     f12:123,
144     numlock:144,
145     scrolllock:145,
146     semicolon:186,
147     ',':186,
148     equal:187,
149     '=':187,
150     ';':188,
151     comma:188,
152     dash:189,
153     '.':190,
154     period:190,
155     forwardslash:191,
156     grave:192,
157     '[':219,
158     openbracket:219,
159     ']':221,
160     closebracket:221,
161     backslash:220,
162     quote:222,
163     space:32
164 };
165 
166 /**
167  * Dispatch the keyboard message
168  * @class
169  * @extends cc.Class
170  */
171 cc.KeyboardDispatcher = cc.Class.extend(/** @lends cc.KeyboardDispatcher# */{
172     /**
173      * add delegate to concern keyboard msg
174      * @param {cc.KeyboardDelegate} delegate keyboard delegate object
175      */
176     addDelegate:function (delegate) {
177         if (!delegate) {
178             return;
179         }
180         if (!this._locked) {
181             this.forceAddDelegate(delegate);
182         }
183         else {
184             this._handlersToAdd.push(delegate);
185             this._toAdd = true;
186         }
187     },
188 
189     /**
190      * remove the delegate from the delegates who concern keyboard msg
191      * @param {cc.KeyboardDelegate} delegate
192      */
193     removeDelegate:function (delegate) {
194         if (!delegate) {
195             return;
196         }
197         if (!this._locked) {
198             this.forceRemoveDelegate(delegate);
199         }
200         else {
201             this._handlersToRemove.push(delegate);
202             this._toRemove = true;
203         }
204     },
205 
206     /**
207      * force add the delegate
208      * @param {cc.KeyboardDelegate} delegate
209      */
210     forceAddDelegate:function (delegate) {
211         var handler = cc.KeyboardHandler.create(delegate);
212         if (handler) {
213             //if handler already exist
214             for (var i = 0; i < this._delegates; i++) {
215                 if (this._delegates[i].getDelegate() == handler.getDelegate()) {
216                 }
217             }
218             this._delegates.push(handler);
219         }
220     },
221 
222     /**
223      * force remove the delegate
224      * @param {cc.KeyboardDelegate} delegate
225      */
226     forceRemoveDelegate:function (delegate) {
227         for (var i = 0; i < this._delegates.length; i++) {
228             if (this._delegates[i].getDelegate() == delegate) {
229                 this._delegates.splice(i, 1);
230                 return;
231             }
232         }
233     },
234 
235     /**
236      * dispatch the keyboard message to the delegates
237      * @param {event} e
238      * @param {Boolean} keydown whether this is a keydown or keyup
239      * @return {Boolean}
240      */
241     dispatchKeyboardMSG:function (e, keydown) {
242         this._locked = true;
243         e.stopPropagation();
244         e.preventDefault();
245 
246         var i = 0;
247         //update keymap
248         if (keydown && e) {     //if keydown and our keymap doesnt have it
249             //execute all deletegate that registered a keyboard event
250             for (i = 0; i < this._delegates.length; i++) {
251                 if(this._delegates[i].getDelegate() && this._delegates[i].getDelegate().onKeyDown)
252                     this._delegates[i].getDelegate().onKeyDown(e.keyCode);
253             }
254         }  else if (!keydown && e) {//if keyup and our keymap have that key in it
255             for (i = 0; i < this._delegates.length; i++) {
256                 if(this._delegates[i].getDelegate() && this._delegates[i].getDelegate().onKeyUp)
257                     this._delegates[i].getDelegate().onKeyUp(e.keyCode);
258             }
259         }
260         this._locked = false;
261         if (this._toRemove) {
262             this._toRemove = false;
263             for (i = 0; i < this._handlersToRemove.length; ++i) {
264                 this.forceRemoveDelegate(this._handlersToRemove[i]);
265             }
266             delete this._handlersToRemove;
267             this._handlersToRemove = [];
268         }
269 
270         if (this._toAdd) {
271             this._toAdd = false;
272             for (i = 0; i < this._handlersToAdd.length; ++i) {
273                 this.forceAddDelegate(this._handlersToAdd[i]);
274             }
275             this._handlersToAdd = [];
276         }
277         return true;
278     },
279 
280     //private
281     _delegates:[],
282     _locked:false,
283     _toAdd:false,
284     _toRemove:false,
285     _handlersToAdd:[],
286     _handlersToRemove:[]
287 });
288 
289 /**
290  * Returns the shared cc.KeyboardDispatcher object for the system.
291  * @return {cc.keyboardDispatcher}
292  */
293 cc.KeyboardDispatcher.getInstance = function () {
294     if (!cc.keyboardDispatcher) {
295         cc.keyboardDispatcher = new cc.KeyboardDispatcher();
296         //make canvas focusable
297         cc.canvas.setAttribute('tabindex', 1);
298         cc.canvas.style.outline = 'none';
299         cc.canvas.style.cursor = 'default';
300         cc.canvas.addEventListener("keydown", function (e) {
301             cc.keyboardDispatcher.dispatchKeyboardMSG(e, true);
302         });
303         cc.canvas.addEventListener("keyup", function (e) {
304             cc.keyboardDispatcher.dispatchKeyboardMSG(e, false);
305         });
306     }
307     return cc.keyboardDispatcher;
308 };
309 
310 /**
311  * Release the shared cc.KeyboardDispatcher object from the system.
312  */
313 cc.KeyboardDispatcher.purgeSharedDispatcher = function () {
314     if (cc.keyboardDispatcher) {
315         delete cc.keyboardDispatcher;
316         cc.keyboardDispatcher = null;
317     }
318 };
319