Just some sharing about java open source and life

Handling Keyboard Shortcuts in JavaScript

日期:2010-03-11 16:58 | 作者:JavaChen | 分类目录:JavaScript
137 views

在web开发中,对页面的进行全局或部分页面进行键盘快捷键事件注册,能够有效的提高页面的用户体验。在ExtJs中的表格Form中就有回车提交的事件,实现方法可以参照我的另一篇文章:Ext监控回车按键
在网络上看到了一篇处理JavaScript键盘快捷键事件的文章:Handling Keyboard Shortcuts in JavaScript ,其实现方法很简单,只是封装了一个shortcut的类,提供了注册快捷键的方法和删除快捷键事件的方法。
其源代码如下,其中代码逻辑很容易看懂而且其中考虑了各种浏览器的兼容问题(可以参照我的上一篇文章:DOM 事件模型)。通过以下代码,可以熟悉如何处理各种浏览器事件处理的兼容性问题。

/**
 * http://www.openjs.com/scripts/events/keyboard_shortcuts/ Version : 2.01.B By
 * Binny V A License : BSD
 * Modified by www.javachen.com  javachen
 */
shortcut = {
	'all_shortcuts' : {},// All the shortcuts are stored in this array
	'add' : function(shortcut_combination, callback, opt) {
		// Provide a set of default options
		var default_options = {
			'type' : 'keydown',//按键事件类型,IE中keypress不支持功能按键,所以应该用keydown/keyup事件来进行补充。
			'propagate' : false,
			'disable_in_input' : false,//是否在input,Textarea内有效
			'target' : document,//事件作用对象,相当于事件的相应范围scope,该值可以为节点的ID
			'keycode' : false
		}
		//处理配置项,如果为空就使用默认的
		if (!opt)
			opt = default_options;
		else {
			for (var dfo in default_options) {
				if (typeof opt[dfo] == 'undefined')
					opt[dfo] = default_options[dfo];
			}
		}

		//如果target为字符串,则通过该字符串取得该DOM对象
		var ele = opt.target;
		if (typeof opt.target == 'string')
			ele = document.getElementById(opt.target);

		var ths = this;//保存当前的this引用
		//联合快捷键
		shortcut_combination = shortcut_combination.toLowerCase();

		// The function to be called at keypress
		var func = function(e) {
			e = e || window.event;//处理浏览器对event的兼容性,只有IE浏览器的event=window.event

			if (opt['disable_in_input']) { // Don't enable shortcut keys in
				// Input, Textarea fields
				var element;
				if (e.target)
					//针对IE浏览器
					element = e.target;
				else if (e.srcElement)
					//针对DOM标准浏览器
					element = e.srcElement;
				//如果当前节点为文本节点,则取其父节点
				if (element.nodeType == 3)
					element = element.parentNode;
				//如果当前节点标签名为INPUT或TEXTAREA,则当前函数不做处理
				if (element.tagName == 'INPUT' || element.tagName == 'TEXTAREA')
					return;
			}

			// Find Which key is pressed
			if (e.keyCode)
			    //针对IE浏览器,e.keyCode返回按键对应的数值
				code = e.keyCode;
			else if (e.which)
			    //针对DOM标准浏览器,如Firefox,e.keyCode返回按键对应的数值
				code = e.which;
			//e.which将给出该键的索引值,把索引值转化成该键的字母或数字值的方法需要用到静态函数String.fromCharCode()
			var character = String.fromCharCode(code).toLowerCase();

			if (code == 188)
				character = ",";
			if (code == 190)
				character = "."; 

			var keys = shortcut_combination.split("+");
			// Key Pressed - counts the number of valid keypresses - if it is
			// same as the number of keys, the shortcut function is invoked
			var kp = 0;

			// Work around for stupid Shift key bug created by using lowercase -
			// as a result the shift+num combination was broken
			var shift_nums = {
				"`" : "~",
				"1" : "!",
				"2" : "@",
				"3" : "#",
				"4" : "$",
				"5" : "%",
				"6" : "^",
				"7" : "&",
				"8" : "*",
				"9" : "(",
				"0" : ")",
				"-" : "_",
				"=" : "+",
				";" : ":",
				"'" : "\"",
				"," : "<",
                                "." : ">",
				"/" : "?",
				"\\" : "|"
			}
			// Special Keys - and their codes
			var 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 modifiers = {
				shift : {
					wanted : false,
					pressed : false//是否被按
				},
				ctrl : {
					wanted : false,
					pressed : false
				},
				alt : {
					wanted : false,
					pressed : false
				},
				meta : {
					wanted : false,
					pressed : false
				} // Meta is Mac specific
			};

			if (e.ctrlKey)
				modifiers.ctrl.pressed = true;
			if (e.shiftKey)
				modifiers.shift.pressed = true;
			if (e.altKey)
				modifiers.alt.pressed = true;
			if (e.metaKey)
				modifiers.meta.pressed = true;

			for (var i = 0; k = keys[i], i < keys.length; i++) {
				// Modifiers
				if (k == 'ctrl' || k == 'control') {
					kp++;
					modifiers.ctrl.wanted = true;

				} else if (k == 'shift') {
					kp++;
					modifiers.shift.wanted = true;

				} else if (k == 'alt') {
					kp++;
					modifiers.alt.wanted = true;
				} else if (k == 'meta') {
					kp++;
					modifiers.meta.wanted = true;
				} else if (k.length > 1) { // If it is a special key
					if (special_keys[k] == code)
						kp++;

				} else if (opt['keycode']) {
					if (opt['keycode'] == code)
						kp++;

				} else { // The special keys did not match
					if (character == k)
						kp++;
					else {
						if (shift_nums[character] && e.shiftKey) { // Stupid
							// Shift key
							// bug
							// created
							// by using
							// lowercase
							character = shift_nums[character];
							if (character == k)
								kp++;
						}
					}
				}
			}
			if (kp == keys.length
					&& modifiers.ctrl.pressed == modifiers.ctrl.wanted
					&& modifiers.shift.pressed == modifiers.shift.wanted
					&& modifiers.alt.pressed == modifiers.alt.wanted
					&& modifiers.meta.pressed == modifiers.meta.wanted) {
				callback(e);

				if (!opt['propagate']) { // Stop the event
					// e.cancelBubble is supported by IE - this will kill the
					// bubbling process.
					e.cancelBubble = true;
					e.returnValue = false;

					// e.stopPropagation works in Firefox.
					if (e.stopPropagation) {
						e.stopPropagation();
						e.preventDefault();
					}
					return false;
				}
			}
		}
		this.all_shortcuts[shortcut_combination] = {
			'callback' : func,
			'target' : ele,
			'event' : opt['type']
		};
		// Attach the function with the event
		if (ele.addEventListener)
			ele.addEventListener(opt['type'], func, false);
		else if (ele.attachEvent)
			ele.attachEvent('on' + opt['type'], func);
		else
			ele['on' + opt['type']] = func;
	},

	// Remove the shortcut - just specify the shortcut and I will remove the
	// binding
	'remove' : function(shortcut_combination) {
		shortcut_combination = shortcut_combination.toLowerCase();
		var binding = this.all_shortcuts[shortcut_combination];
		delete(this.all_shortcuts[shortcut_combination])
		if (!binding)
			return;
		var type = binding['event'];
		var ele = binding['target'];
		var callback = binding['callback'];

		if (ele.detachEvent)
			ele.detachEvent('on' + type, callback);
		else if (ele.removeEventListener)
			ele.removeEventListener(type, callback, false);
		else
			ele['on' + type] = false;
	}
}
作者:JavaChen | 分类目录:JavaScript | 标签:
回到顶部

无觅相关文章插件,快速提升流量