javascript键盘事件管理工具

最近在开发一个在线IDE。
在线IDE其中很重要的一个难点是如何处理好快捷键的事件绑定
针对这个问题我写了一个库来管理快捷键事件:
比如按下alt+/  提示代码
ctrl+enter 执行代码
ctrl+d 删除一行代码

lib.js类库代码如下:
var lib = (function() {
	var addListener = function(element, eventType, func, args) {
		var eventHandler = func;
		if (args) {
			eventHandler = function(e) {
				func.call(this, e, args);
			}
		}
		if (element.addEventListener) {
			element.addEventListener(eventType, eventHandler, false);
		} else if (ele.attachEvent) {
			element.attachEvent('on' + eventType, eventHandler);
		} else {
			element['on' + eventType] = eventHandler;
		}
	};
	var toString = Object.prototype.toString, class2type;
	var type = function(obj) {
		if (!class2type) {
			var class2type = {}, arr = "Boolean Number String Function Array Date RegExp Object"
					.split(" ");
			while (arr.length > 0) {
				var name = arr.pop();
				class2type["[object " + name + "]"] = name.toLowerCase();
			}
		}
		return obj == null ? String(obj) : class2type[toString.call(obj)]
				|| "object";
	};
	var shift_nums = {
		"`" : "~",
		"1" : "!",
		"2" : "@",
		"3" : "#",
		"4" : "$",
		"5" : "%",
		"6" : "^",
		"7" : "&",
		"8" : "*",
		"9" : "(",
		"0" : ")",
		"-" : "_",
		"=" : "+",
		";" : ":",
		"'" : "\"",
		"," : "<",
		"." : ">",
		"/" : "?",
		"\\" : "|"
	}, number_keys = {
		"`" : 192,
		"1" : 49,
		"2" : 50,
		"3" : 51,
		"4" : 52,
		"5" : 53,
		"6" : 54,
		"7" : 55,
		"8" : 56,
		"9" : 57,
		"0" : 48,
		"-" : 189,
		"=" : 187,
		";" : 186,
		"'" : 222,
		"\"" : 16,
		"," : 188,
		"." : 190,
		"/" : 191,
		"\\" : 220
	},
	// Special Keys - and their codes
	special_keys = {
		'esc' : 27,
		'escape' : 27,
		'tab' : 9,
		'space' : 32,
		'return' : 13,
		'enter' : 13,
		'backspace' : 8,

		'scrolllock' : 145,
		'scroll_lock' : 145,
		'scroll' : 145,
		'capslock' : 20,
		'caps_lock' : 20,
		'caps' : 20,
		'numlock' : 144,
		'num_lock' : 144,
		'num' : 144,

		'pause' : 19,
		'break' : 19,

		'insert' : 45,
		'home' : 36,
		'delete' : 46,
		'end' : 35,

		'pageup' : 33,
		'page_up' : 33,
		'pu' : 33,

		'pagedown' : 34,
		'page_down' : 34,
		'pd' : 34,

		'left' : 37,
		'up' : 38,
		'right' : 39,
		'down' : 40,

		'f1' : 112,
		'f2' : 113,
		'f3' : 114,
		'f4' : 115,
		'f5' : 116,
		'f6' : 117,
		'f7' : 118,
		'f8' : 119,
		'f9' : 120,
		'f10' : 121,
		'f11' : 122,
		'f12' : 123
	};

	var adaptor = function(e, key_combination, callback) {
		if (e.keyCode)
			code = e.keyCode;
		else if (e.which)
			code = e.which;
		var character = String.fromCharCode(code).toLowerCase();
		var keys = key_combination.split("+");
		var kp = 0;
		var modifiers = {};
		modifiers.ctrl = true, modifiers.shift = true, modifiers.alt = true;
		if (e.ctrlKey)
			modifiers.ctrl = false;
		if (e.shiftKey)
			modifiers.shift = false;
		if (e.altKey)
			modifiers.alt = false;

		for (var i = 0, len = keys.length;k = keys[i], i < len; i++) {
			// Modifiers
			if (k == 'ctrl' || k == 'control') {
				kp++;
				modifiers.ctrl = !modifiers.ctrl;
			} else if (k == 'shift') {
				kp++;
				modifiers.shift = !modifiers.shift;
			} else if (k == 'alt') {
				kp++;
				modifiers.alt = !modifiers.alt;
			} else if (special_keys[k] == code) {
				kp++;
			} else if (character == k) {
				kp++;
			} else if (number_keys[k] == code) {
				kp++;
			} else {
				if (shift_nums[character] && e.shiftKey) {
					character = shift_nums[character];
					if (character == k)
						kp++;
				}
			}
		}
		if (kp == keys.length && modifiers.ctrl && modifiers.shift
				&& modifiers.alt) {
			if (callback) {
				callback(e);
				if (e.stopPropagation) {
					e.stopPropagation();
					e.preventDefault();
				}
			}
			return true;
		}
	};
	var splitCombination = function(e, key_combination, callback) {
		var keys = key_combination.split("|");
		for (var i = 0;i < keys.length; i++) {
			if (adaptor(e, keys[i], callback)) {
				return true;
			}
		}
	};
	var handler = function(evt, opt) {
		var funcs = opt["funcs"], publicHandler = opt["commonHandler"];;
		for (var i = 0;i < funcs.length; i++) {
			var func = funcs[i];
			var k = func["keyComb"], h = func["handler"], doit = func["docommon"];
			if (splitCombination(evt, k)) {
				var stop = func["stop"], prevent = func["prevent"];
				h.call(this, evt, k);
				if (stop && evt.stopPropagation) {
					evt.stopPropagation();
				}
				if (prevent && evt.preventDefault) {
					evt.preventDefault();
				}
				if (publicHandler && doit) {
					publicHandler.call(this, evt,func);
				}
				break;
			}
		}
	};
	var handlerEvent = function(evt, args) {
		switch (evt.type) {
			case "keydown" :
				handler(evt, args);
				break;
			case 'keypress' :
				handler(evt, args);
				break;
			case 'keyup' :
				handler(evt, args);
				break;
		}
		// evt.preventDefault();
	};
	/**
	 * @param element
	 *            被注册事件页面元素
	 * @param eventType
	 *            事件类型 eg:click、keyup
	 * @param opt
	 *            事件处理的回调函数、或者是一个特定的事件对象数组
	 *            [{keyComb:"alt+/",handler:func,stop:false}]
	 */
	var register = function(element, eventType, opt) {
		if (type(opt) === 'function') {
			addListener(element, eventType, opt);
		} else if (type(opt) === 'object') {
			addListener(element, eventType, handlerEvent, opt);
		}
	};
	return {
		register : register
	}
}());



测试页面代码如下;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
	<head>
		<title>MyHtml.html</title>

		<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
		<meta http-equiv="description" content="this is my page">
		<meta http-equiv="content-type" content="text/html; charset=UTF-8">
		<style type="text/css">
body {
	margin: 30px;
	line-height: 16px;
}
</style>
		<script type="text/javascript" src="lib.js"></script>
		<script type="text/javascript" src="libtest.js"></script>
	</head>

	<body>
		<pre contenteditable="true">22</pre>
	</body>
</html>


libtest.js
window.addEventListener('load', function() {
	var pre = document.getElementsByTagName("pre")[0];
	// lib.register(pre,"click",function(){alert("pre")});
		var handler = function(e, k) {
			console.log(k);
		};
		var commonHandler = function() {
			console.log("execute commonHandler");
		};
		var keydown_opt = {
			funcs : [ {
				keyComb : "alt+/",
				handler : handler
			}, {
				keyComb : "ctrl+s",
				handler : handler,
				stop : true,
				prevent : true
			}, {
				keyComb : "tab",
				handler : handler,
				stop : true,
				prevent : false
			}, {
				keyComb : "a|b|c|d|'",
				handler : handler,
				stop : true,
				prevent : false
			}]
		};
//当需要捕获类似于{ "这样的字符的时候 需要加上shift
		var keypress_opt = {
			commonHandler : commonHandler,
			funcs : [{
				keyComb : "shift+{|shift+\"",
				handler : handler,
				stop : true,
				prevent : false,
				docommon : true
			}]
		};
		lib.register(pre, "keydown", keydown_opt);
		lib.register(pre, "keypress", keypress_opt);
	}, true);

监听键盘按下事件配置项                                                           
配置项有两个参数:                                                          
		  funcs:array                                                                 
		  	一个对象数组,数组中每个对象对应着一个快捷键处理对象keyCombHandler          
		  commonHandler:function                                                     
		  公共的回调函数, 所有按键都可能回触发的回调函数,                            
		  如果keyCombHandler对象中的docommon设置为true则keyCombHandler会执行该回调函数
		                                                                              
快捷键处理对象:                                                         
		  keyCombHandler:Object                                                       
		  快捷键处理对象,每个快捷键对应一个对象、该对象可以配置十分取消默认的行为、是否阻止事件冒泡等。请参照下面的属性                                                                          
		  配置属性                                                                    
		  keyComb:String                                                              
		  	组合快捷键 比如alt+/或 a|b|c|d (|表示或  +表示与)                                                  
		  handler:function                                                            
		  	按下相应的快捷键后触发的处理函数                                           
		  stop:boolean                                                                
		  	是否阻止事件冒泡 默认false                                                           
		  prevent:boolean                                                             
		  	是否取消默认的事件 默认false                                                         
		  docommon:boolean                                                            
		  	是否执行公共的回调函数 默认false 

你可能感兴趣的:(JavaScript)