| 
									
										
										
										
											2013-02-26 01:52:57 +04:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //var DEBUG = DEBUG != null ? DEBUG : true
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NOTE: don't understand why am I the one who has to write this...
 | 
					
						
							|  |  |  | var SPECIAL_KEYS = { | 
					
						
							|  |  |  | 	// Special Keys...
 | 
					
						
							|  |  |  | 	9:		'Tab',		33:		'PgUp',		45:		'Ins',		 | 
					
						
							|  |  |  | 	13:		'Enter',	34:		'PgDown',	46:		'Del',		 | 
					
						
							|  |  |  | 	16:		'Shift',	35:		'End',		80:		'Backspace', | 
					
						
							|  |  |  | 	17:		'Ctrl',		36:		'Home',		91:		'Win',		 | 
					
						
							| 
									
										
										
										
											2013-03-02 20:08:41 +04:00
										 |  |  | 	18:		'Alt',		37:		'Left',		93:		'Menu',		 | 
					
						
							| 
									
										
										
										
											2013-02-26 01:52:57 +04:00
										 |  |  | 	20:		'Caps Lock',38:		'Up',	  | 
					
						
							| 
									
										
										
										
											2013-03-02 20:08:41 +04:00
										 |  |  | 	27:		'Esc',		39:		'Right',   | 
					
						
							| 
									
										
										
										
											2013-02-26 01:52:57 +04:00
										 |  |  | 	32:		'Space',	40:		'Down',   | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Function Keys...
 | 
					
						
							|  |  |  | 	112:	'F1',		116:	'F5',		120:	'F9',  | 
					
						
							|  |  |  | 	113:	'F2',		117:	'F6',		121:	'F10', | 
					
						
							|  |  |  | 	114:	'F3',		118:	'F7',		122:	'F11', | 
					
						
							|  |  |  | 	115:	'F4',		119:	'F8',		123:	'F12', | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-28 02:50:55 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-26 01:52:57 +04:00
										 |  |  | // XXX some keys look really wrong...
 | 
					
						
							|  |  |  | function toKeyName(code){ | 
					
						
							|  |  |  | 	// check for special keys...
 | 
					
						
							|  |  |  | 	var k = SPECIAL_KEYS[code] | 
					
						
							|  |  |  | 	if(k != null){ | 
					
						
							|  |  |  | 		return k | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// chars...
 | 
					
						
							|  |  |  | 	k = String.fromCharCode(code) | 
					
						
							|  |  |  | 	if(k != ''){ | 
					
						
							| 
									
										
										
										
											2013-03-02 19:57:26 +04:00
										 |  |  | 		//return k.toLowerCase()
 | 
					
						
							|  |  |  | 		return k | 
					
						
							| 
									
										
										
										
											2013-02-26 01:52:57 +04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return null | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-02 19:57:26 +04:00
										 |  |  | function chr(c){ | 
					
						
							|  |  |  | 	return c.charCodeAt(0) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-26 01:52:57 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | // if set to false the event handlers will always return false...
 | 
					
						
							|  |  |  | var KEYBOARD_HANDLER_PROPAGATE = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Basic key format: | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-03-02 20:43:49 +04:00
										 |  |  |  * 		<key-def> : <callback>, | 
					
						
							| 
									
										
										
										
											2013-02-26 01:52:57 +04:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-03-02 20:43:49 +04:00
										 |  |  |  * 		<key-def> : { | 
					
						
							| 
									
										
										
										
											2013-02-26 01:52:57 +04:00
										 |  |  |  * 			'default': <callback>, | 
					
						
							|  |  |  |  *			// a modifier can be any single modifier, like shift or a 
 | 
					
						
							|  |  |  |  *			// combination of modifers like 'ctrl+shift', given in order 
 | 
					
						
							|  |  |  |  *			// of priority.
 | 
					
						
							|  |  |  |  *			// supported modifiers are (in order of priority):
 | 
					
						
							|  |  |  |  *			//	- ctrl
 | 
					
						
							|  |  |  |  *			//	- alt
 | 
					
						
							|  |  |  |  *			//	- shift
 | 
					
						
							|  |  |  |  * 			<modifer>: [...] | 
					
						
							|  |  |  |  * 		}, | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-03-02 20:43:49 +04:00
										 |  |  |  * 		<key-def> : [ | 
					
						
							| 
									
										
										
										
											2013-02-26 01:52:57 +04:00
										 |  |  |  *			// this can be any type of handler except for an alias...
 | 
					
						
							|  |  |  |  * 			<handler>,  | 
					
						
							|  |  |  |  * 			<doc> | 
					
						
							|  |  |  |  * 		], | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *		// alias...
 | 
					
						
							| 
									
										
										
										
											2013-03-02 20:43:49 +04:00
										 |  |  |  * 		<key-def-a> : <key-def-b>, | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * <key-def> can be: | 
					
						
							|  |  |  |  * 	- explicit key code | 
					
						
							|  |  |  |  * 	- key name, if present in SPECIAL_KEYS) | 
					
						
							|  |  |  |  * 	- key char (uppercase), as is returned by String.fromCharCode(...)  | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-02-26 01:52:57 +04:00
										 |  |  |  * | 
					
						
							|  |  |  |  * XXX might need to add meta information to generate sensible help... | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function makeKeyboardHandler(keybindings, unhandled){ | 
					
						
							|  |  |  | 	if(unhandled == null){ | 
					
						
							|  |  |  | 		//unhandled = function(){return false}
 | 
					
						
							|  |  |  | 		unhandled = function(){return KEYBOARD_HANDLER_PROPAGATE} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return function(evt){ | 
					
						
							|  |  |  | 		var did_handling = false | 
					
						
							|  |  |  | 		var res = null | 
					
						
							|  |  |  | 		for(var mode in keybindings){ | 
					
						
							|  |  |  | 			if($(mode).length > 0){ | 
					
						
							|  |  |  | 				var bindings = keybindings[mode] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				var key = evt.keyCode | 
					
						
							| 
									
										
										
										
											2013-03-02 19:57:26 +04:00
										 |  |  | 				var chr = toKeyName(evt.keyCode) | 
					
						
							| 
									
										
										
										
											2013-02-26 01:52:57 +04:00
										 |  |  | 				if(bindings.ignore == '*'  | 
					
						
							|  |  |  | 						|| bindings.ignore != null && bindings.ignore.indexOf(key) != -1){ | 
					
						
							|  |  |  | 					// return true
 | 
					
						
							|  |  |  | 					res = res == null ? true : res | 
					
						
							|  |  |  | 					did_handling = true | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// XXX ugly...
 | 
					
						
							|  |  |  | 				var modifers = evt.ctrlKey ? 'ctrl' : '' | 
					
						
							|  |  |  | 				modifers += evt.altKey ? (modifers != '' ? '+alt' : 'alt') : '' | 
					
						
							|  |  |  | 				modifers += evt.shiftKey ? (modifers != '' ? '+shift' : 'shift') : '' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-02 19:57:26 +04:00
										 |  |  | 				if(chr in bindings){ | 
					
						
							|  |  |  | 					var handler = bindings[chr] | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					var handler = bindings[key] | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2013-02-26 01:52:57 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// alias...
 | 
					
						
							|  |  |  | 				while (typeof(handler) == typeof(123)) { | 
					
						
							|  |  |  | 					handler = bindings[handler] | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// no handler...
 | 
					
						
							|  |  |  | 				if(handler == null){ | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// Array, lisp style with docs...
 | 
					
						
							|  |  |  | 				// XXX for some odd reason in chrome typeof([]) == typeof({})!!!
 | 
					
						
							|  |  |  | 				if(typeof(handler) == typeof([]) && handler.constructor.name == 'Array'){ | 
					
						
							|  |  |  | 					// we do not care about docs here, so just get the handler...
 | 
					
						
							|  |  |  | 					handler = handler[0] | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// complex handler...
 | 
					
						
							|  |  |  | 				if(typeof(handler) == typeof({})){ | 
					
						
							|  |  |  | 					var callback = handler[modifers] | 
					
						
							|  |  |  | 					if(callback == null){ | 
					
						
							|  |  |  | 						callback = handler['default'] | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					if(callback != null){ | 
					
						
							|  |  |  | 						res = callback() | 
					
						
							|  |  |  | 						did_handling = true | 
					
						
							|  |  |  | 						continue | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					// simple callback...
 | 
					
						
							|  |  |  | 					res = handler()  | 
					
						
							|  |  |  | 					did_handling = true | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(!did_handling){ | 
					
						
							|  |  |  | 			// key is unhandled by any modes...
 | 
					
						
							|  |  |  | 			return unhandled(key) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// XXX should we handle multiple hits???
 | 
					
						
							|  |  |  | 			return KEYBOARD_HANDLER_PROPAGATE&&res?true:false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 :                                                */ |