在互联网上关于javascript快捷键实现的方式寥寥无几,而且不能满足当前项目要求,应项目组要求关于网页快捷键提供一个相对通用的解决方案,因此产生此篇文章。
一、项目需求:
1、使用键盘上的左、右键在各个控件之间进行焦点转移。左键向上转移焦点(类似与shift+tab键);右键向下转移焦点(类似与tab键)。
2、使用键盘上下键在列表中上下转移焦点。
3、能够使用enter、esc键进行form表单数据保存、取消。
二、总体思路:
html各控件本身都提供了tab-index属性,设置该属性后通过tab键就可以实现焦点在各控件间按照tab-index值,由小到大进行焦点转移。
1、在网页进行装载(调用body的onload事件)时候将所有具有tab-index的控件放入Array数组中,按照tab-index值排序。
2、在按左、右键的时,定位当前控件,然后在定位Array中的前一个或后一个控件,然后让该控件获得焦点。
3、关于上、下键进行表单跳转,强制要求元素必须在html的table表格中,通过表格的上下td进行焦点转移,具体实现可以参见实现代码。
三、实现代码:
实现由一个js文件和一个html测试页面组成。
1、hotkey.js文件,该文件以prototype方式定义HotKey类,该类包括快捷键定义、上下左右转移方法实现、快捷键注册方法。具体内容如下所示:
var __KEY_ADDNEW = 65; var __KEY_SAVE = 13; var __KEY_ESC = 27; var __KEY_LEFT = 37; var __KEY_RIGHT = 39; var __KEY_UP = 38; var __KEY_DOWN = 40; function HotKey(){ this.keyArray = new Array(); this.tabArray = new Array(); //this._self = this; var _self = this; var _arr = new Array(); _arr.push(this); this.registerKey(__KEY_LEFT,this.movetoprevious,_arr); this.registerKey(__KEY_RIGHT,this.movetonext,_arr); this.registerKey(__KEY_DOWN,this.movetodown); this.registerKey(__KEY_UP,this.movetoup); } HotKey.prototype.loadTabElements = function(){ var _ele = document.getElementsByTagName("input"); for(var i=0;i<_ele.length;i++){ if(null!=_ele[i].getAttribute("tabIndex")){ this.tabArray.push({"tabIndex":_ele[i].getAttribute("tabIndex"),"element":_ele[i]}); } } this.tabArray.sort(function compare(a,b){ return Number(a.tabIndex)-Number(b.tabIndex); } ); } HotKey.prototype.getTabArray=function(){ return this.tabArray; } //转移到下一个焦点(tab) HotKey.prototype.movetonext=function(p_hotkey){ var _array = p_hotkey.getTabArray(); if(event.srcElement==_array[_array.length-1].element){ _array[0].element.focus(); _array[0].element.select(); return; } for(var i=0;i<_array.length;i++){ if(event.srcElement==_array[i].element){ if(null!=_array[i+1]){ _array[i+1].element.focus(); _array[i+1].element.select(); } } } } //转移到上一个焦点(shift+tab) HotKey.prototype.movetoprevious=function(p_hotkey){ var _array = p_hotkey.getTabArray(); if(event.srcElement==_array[0].element){ _array[_array.length-1].element.focus(); _array[_array.length-1].element.select(); return; } for(var i=_array.length-1;i>-1;i--){ if(event.srcElement==_array[i].element){ if(null!=_array[i-1]){ _array[i-1].element.focus(); _array[i-1].element.select(); } } } } HotKey.prototype.movetodown=function(){ var _td = event.srcElement.parentNode; var _tr = _td.parentNode; var _tbl = _tr.parentNode.parentNode; if(null==_tbl || "TABLE"!=_tbl.tagName) return; var k = 0; for(var i=0;i<_tr.cells.length;i++){ if(_td==_tr.cells[i]) { k=i; break; } } var _nexttr = _tr.nextSibling; if(null==_nexttr) return; _nexttr.cells[k].childNodes[0].focus(); _nexttr.cells[k].childNodes[0].select(); } HotKey.prototype.movetoup=function(){ var _td = event.srcElement.parentNode; var _tr = _td.parentNode; var _tbl = _tr.parentNode.parentNode; if(null==_tbl || "TABLE"!=_tbl.tagName) return; var k = 0; for(var i=0;i<_tr.cells.length;i++){ if(_td==_tr.cells[i]) { k=i; break; } } var _previousttr = _tr.previousSibling; if(null==_previousttr) return; _previousttr.cells[k].childNodes[0].focus(); _previousttr.cells[k].childNodes[0].select(); } HotKey.prototype.registerKey=function(p_key,p_callback,p_args){ //判断是否重复注册,新的替换旧的; var isexist = false; for(var i=0;i<this.keyArray.length;i++){ if(p_key==this.keyArray[i].key){ this.keyArray[i]={"key":p_key,"_callback":p_callback,"_args":p_args}; isexist=true; } } if(!isexist){ this.keyArray.push({"key":p_key,"_callback":p_callback,"_args":p_args}); } var _self = this; document.οnkeydοwn=function(){ for(var i=0;i<_self.keyArray.length;i++){ if(event.keyCode==_self.keyArray[i].key){ if(null==_self.keyArray[i]._args || _self.keyArray[i]._args=="undefined"){ var _array = new Array(); _array.push(event); _self.keyArray[i]._callback.apply(this,_array); }else{ _self.keyArray[i]._args.push(event); _self.keyArray[i]._callback.apply(this,_self.keyArray[i]._args); } event.returnValue=false; break; } } } }
2、hotkey.htm文件,用来演示快捷键实现的参考样例。代码如下所示:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=gbk" />
<meta http-equiv="content-language" content="zh-CN" />
<title> new document </title>
<script language=JScript.Encode src="hotkey.js"></script>
<style type="text/css">
*:focus {
border:1px dotted blue;
}
</style>
</head>
<body οnlοad="hotkey.loadTabElements();">
<input type="text" name="oo" tabIndex="1" value="1">
<table id="tt" border="1">
<tr>
<td>1</td>
<td><input id="yy" type="checkbox" tabIndex="2"><input id="yyy" type="hidden"></td>
<td id="11"><input name="kk[0]" value="0000" tabIndex="3"></td>
<td> </td><td><input name="jj[0]" value="00001111" tabIndex="4"></td>
<td> </td>
</tr>
<tr>
<td>2</td><td><input type="checkbox" tabIndex="5"><input id="yyy" type="hidden"></td> <td><input name="kk[1]" tabIndex="6"></td><td> </td><td><input name="jj[1]" tabIndex="7"> </td><td> </td>
</tr>
</table>
<input type="text" name="yy" tabIndex="8">
<input type="text" name="tt" tabIndex="9">
<br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<script language="JavaScript">
<!--
var hotkey = new HotKey();
var arr = new Array();
arr.push("save is ok");
hotkey.registerKey(__KEY_SAVE,toSave,arr);
hotkey.registerKey(__KEY_ESC,toEsc,null);
//hotkey.registerKey(__KEY_UP,toup,null);
function toup(){
alert("toup");
}
function toSave(v){
alert(v);
}
function toEsc(){
alert("esc");
}
//-->
</script>
</body>
</html>
说明:
1、在页面设计时指定进行焦点停留控件的tab-index属性值。
2、在页面加载时,必须指定body的οnlοad=hotkey.loadTabElements()。
3、可以使用registerKey方法对程序中已经注册的键盘事件进行复写。