`

Ext 实现虚拟键盘

阅读更多
对于一些安全性较高的网站,提供虚拟键盘功能,自己基于Ext3实现了虚拟键盘功能,所实现的功能有:
  • 指定事件,当这个事件触发时,虚拟键盘显示出来,默认是focus事件
  • 指定是否启用按钮位置混淆,默认是true,表示每次显示出来时,位置都不一样
  • 有大小写转换开关,shift开关,控制录入字符的大小写
  • 键盘自动计算显示的位置,不必担心在浏览器边上显示不全


此虚拟键盘是以插件的形式来实现的,使用起来很方便,代码如下:
/* 键盘
 * author:Daniel
 * createTime:2010-10-24 21:46
 * usage: plugins : [keyboard]
 ******************************************************************************/
 
 Ext.ux.KeyBoard = Ext.extend(Ext.ToolTip,{
 	wander : true,//启用按钮位置混淆
 	showEvents : 'focus',
 	boxMinWidth : 328,
 	boxMaxWidth : 328,
 	height : 103,
 	plain : true,
 	autoHide: false,
 	chars : {
 		'`':'`', '1':'!', '2':'@', '3':'#', '4':'$', '5':'%', '6':'^', '7':'&', '8':'*', '9':'(', '0':')',
 		'-':'_', '=':'+', ',':'<', '.':'>', '/':'?', ';':':', '\'':'"','[':'{', ']':'}', '\\':'|', '←':'←',
 		'Shift':'Shift', 'Caps Lock':'Caps Lock', '清空':'清空'
 	},

	posC:['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'],
	posN : ['0','1','2','3','4','5','6','7','8','9'],
 	init : function(field){
 		
 		if(!Ext.isIE){
 			this.autoWidth = true;
 		}
 		
 		this.btns = new Ext.Container({
 			ref : 'kbPanel',
 			width : Ext.isIE?318:320,
 			height : 103,
 			style : 'margin : -2px;',
 			layout : 'absolute',
 			defaults : {
 				width : 20
 			},
 			defaultType : 'button',
 			items : [{ 
 				text : "1", x : 2, y : 3 },{
				text : "2", x : 25, y : 3 },{
				text : "3", x : 48, y : 3 },{	
				text : "4", x : 71, y : 3 },{		
				text : "5", x : 94, y : 3 },{
				text : "6", x : 117, y : 3 },{
				text : "7", x : 140, y : 3 },{
				text : "8", x : 163, y : 3 },{			
				text : "9", x : 186, y : 3 },{			
				text : "0", x : 209, y : 3 },{	
				text : "←", width : 40, x : 278, y : 3 },{		
				text : "Shift", ref : '../kbShift', enableToggle : true, width : 63,x : 2,y : 53 },{
				text : 'Caps Lock', ref : '../kbCapsLock', enableToggle : true, width : 63 ,x : 2, y : 28 },{	
				text : "a", x : 68, y : 28 },{
				text : "c", x : 114, y : 28 },{		
				text : "b", x : 91, y :28},{	
				text : "d", x : 137, y : 28 },{			
				text : "e", x : 160, y : 28 },{
				text : "g", x : 206, y : 28 },{	
				text : "f", x : 183, y : 28 },{
				text : "i", x : 252, y : 28 },{	
				text : "j", x : 275, y : 28 },{	
				text : "h", x : 229, y : 28 },{	
				text : "k", x : 298, y : 28 },{	
				text : "l", x : 68, y : 53 },{
				text : "p", x : 160, y : 53 },{	
				text : "m", x : 91, y : 53 },{
				text : "n", x : 114, y : 53 },{		
				text : "o", x : 137, y : 53 },{	
				text : "r", x : 206, y : 53 },{			
				text : "s", x : 229, y : 53 },{	
				text : "t", x : 252, y : 53 },{	
				text : "q", x : 183, y : 53 },{	
				text : "u", x : 275, y : 53 },{	
				text : "v", x : 298, y : 53 },{
				text : "w", x : 68, y : 78 },{	
				text : "x", x : 45, y : 78 },{
				text : "z", x : 114, y : 78 },{	
				text : "y", x : 91, y : 78 },{
				text : "清空", ref : '../kbClear',width : 40,x : 2, y : 78 },{		
				text : "=", x : 255, y : 3 },{	
				text : "-", x : 232, y : 3 },{	
				text : "`", x : 137, y : 78 },{	
				text : "[", x : 252, y : 78 },{	
				text : "]", x : 275, y : 78 },{
				text : ";", x : 160, y : 78 },{
				text : "'", x : 183, y : 78 },{
				text : ",", x : 206, y : 78 },{	
				text : ".", x : 229, y : 78 },{
				text : "/", x : 298, y : 78
			}]
 		});
 		
 		this.add(this.btns);
 		this.doHandlers(field);
 		this.mon(this,'show',this.doWander,this);
 	},
 	
 	doHandlers : function(field){
 		 //给每个按钮加监听器
		for(var i=0;i<this.btns.items.length;i++){
			this.btns.items.get(i).on('click',function(obj){
				switch(obj.text){
 					case 'Caps Lock':
 						this.doCapsLock(field);
 						break;
 					case 'Shift':
 						this.doShift(field);
 						break;
 					case '清空':
 						this.doClear(field);
 						break;
 					case '←':
 						this.doBackspace(field);
 						break;
 					default:
 						this.doClicked(obj,field);
	 			}
			},this);
 		}
 		
 		//处理事件
 		field.on(this.showEvents,function(){
 			var posArr = field.getPosition();
 			var viewWidth = document.body.scrollWidth;//网页可见区宽度
 			var viewHeight = document.body.scrollHeight;//网页可见区高度
 			var posXY = [];
 			if((viewWidth-posArr[0]-field.getWidth()-328)>=0){
 				posXY.push(posArr[0]+field.getWidth());
 				posXY.push(posArr[1]);
 			}else if((viewWidth-posArr[0]-328)>=0){
 				posXY.push(posArr[0]);
 				var tmp = viewHeight-posArr[1]-field.getHeight()-103;
 				posXY.push(tmp>=0?(posArr[1]+this.getHeight()):(posArr[1]-103));
 			}else if((viewWidth-posArr[0]-328)<0){
 				posXY.push(posArr[0]-328);
 				var tmp = viewHeight-posArr[1]-field.getHeight()-103;
 				posXY.push(tmp>=0?(posArr[1]+this.getHeight()):(posArr[1]-103));
 			}else{
 				posXY = [posArr[0],posArr[1]+field.getHeight()];
 			}
 			this.showAt(posXY);
 		},this);
 		
 	},
 	
 	doBackspace : function(field){
 		var oldV = field.getValue();
 		var newV = oldV.substring(0,oldV.length-1);
 		field.setValue(newV);
 	},
 	
 	//处理所有按钮的点击事件
 	doClicked : function(obj,field){
 		field.setValue(field.getValue() + obj.text);
 	},
 	
 	//清除文本框的内容
 	doClear : function(field){
 		field.setValue('');
 	},
 	
 	//点击了Shift键
 	doShift : function(){
 		this.kbShift.clicked = !this.kbShift.clicked;
 		var regex = /^[a-z]{1}$/i;
 		for(var i=0;i<this.btns.items.length;i++){
 			var txt = this.btns.items.get(i).text;
 			var ascii = txt.charCodeAt(0);
 			if(txt.match(regex)){//是字母
 				this.btns.items.get(i).setText(this.kbShift.clicked?txt.toUpperCase():txt.toLowerCase());
 			}else{
 				var tmp = this.chars[txt];
 				this.btns.items.get(i).setText(tmp);
 				delete this.chars[txt];
 				this.chars[tmp] = txt;
 			}
 		}
 	},
 	
 	//点击了CapsLock
 	doCapsLock : function(){
 		//this.kbCapsLock	取得CapsLock键
 		var regex = /^[a-zA-Z]{1}$/;
 		this.kbCapsLock.clicked = !this.kbCapsLock.clicked;
 		for(var i=0;i<this.btns.items.length;i++){
 			var txt = this.btns.items.get(i).text;
 			if(txt.match(regex)){
 				this.btns.items.get(i).setText(this.kbCapsLock.clicked?txt.toUpperCase():txt.toLowerCase());
 			}
 		}
 	},
 	
 	//混淆按钮位置
 	doWander : function(){
 		if(!this.wander){
			return;
		}
 		
 		var regexC = /^[a-zA-Z]{1}$/;
 		var regexN = /^\d+$/;
 		var ghostC = this.posC;
 		var ghostN = this.posN;
 		for(var i=0;i<this.btns.items.length;i++){
 			var posxy;
 			var obj = this.btns.items.get(i);
 			if((obj.text.length == 1) && obj.text.match(regexC)){//是字母
	 			var cIndex = OA.utils.randomNum(0,this.posC.length-1);
	 			obj.setText(this.posC[cIndex]);
	 			this.posC = OA.utils.arrayDelte(this.posC,cIndex);
	 		}else if(obj.text.match(regexN)){//是数字
	 		 	var nIndex = OA.utils.randomNum(0,this.posN.length-1);
	 			obj.setText(this.posN[nIndex]);
	 			this.posN = OA.utils.arrayDelte(this.posN,nIndex);
	 		}
//	 		alert(obj.text + (obj.text.length == 1) + '\t'+this.posC.length+'\t'+this.posN.length);
	 		
 		}
 		this.posC = ghostC;
 		this.posN = ghostN;
 		
 	},
 	
 	getPType : function(){
 		return this.ptype;
 	}
 });
 Ext.preg('keyboard',Ext.ux.KeyBoard);


插件中使用到的两个函数代码如下:
/**
	 * 删除数组中的一个元素,给了元素的索引即可
	 * 
	 * @param {}
	 *            index
	 * @return {}
	 */
	arrayDelte : function(arr, index) {
		if (index < 0)
			return arr;
		return arr.slice(0, index).concat(arr.slice(index + 1, arr.length));
	},
	/**
	 * 产生从start开始到end结束的随机数字
	 * @param {}
	 *            start
	 * @param {}
	 *            end
	 */
	randomNum : function(start, end) {
		return parseInt(Math.random() * (end - start + 1) + start);
	}

实现的效果图如下所示:
  • 大小: 16.1 KB
分享到:
评论

相关推荐

    EXT动态新增一行

    7. **用户交互**:为了提供良好的用户体验,可能还需要实现删除行、编辑行等功能,并处理好各种用户交互,如键盘导航、焦点管理等。 通过以上步骤,你可以构建出一个具备动态新增行功能的EXT应用。EXT提供了丰富的...

    Ext Js权威指南(.zip.001

    10.1.6 虚拟滚动条的工作原理:ext.grid.pagingscroller / 511 10.1.7 锁定列的运行流程:ext.grid.lockable与ext.grid.lockingview / 516 10.2 使用grid / 520 10.2.1 最简单的grid / 520 10.2.2 列的配置项 /...

    Extjs软键盘带中文输入

    在标题和描述中提到的"Extjs软键盘带中文输入",指的是在ExtJS应用中集成一种虚拟键盘功能,支持中文字符的输入,包括中文拼音和五笔输入。 在Web应用中,由于浏览器安全限制,通常不能直接操作系统的物理键盘,...

    一个操作系统的实现(光盘)

    6. 文件系统:理解FAT、EXT、NTFS等常见文件系统的工作原理,学习如何设计和实现自己的文件系统。 7. 系统调用:操作系统提供给用户程序的接口,学习如何定义和实现系统调用。 8. 安全性与稳定性:理解权限模型、...

    OpenXR-OverlayLayer:将OpenXR Overlay扩展实现为一层

    虚拟键盘 对XR_EXTX_overlay实验性扩展旨在证明概念并发现问题。 要解决的一些问题包括: 建立安全和访问控制要求 如何解决输入焦点要求 我们希望在解决所有问题之后,OpenXR运行时将包含扩展的将来版本,并且可能...

    疯狂内核之——虚拟文件系统

    在Linux操作系统中,所有设备都被抽象成文件的形式,无论是磁盘、串口还是键盘鼠标,都被视为一个文件。这种将不同类型的硬件资源统一抽象成文件的方式,形成了Linux中的“一切皆文件”的哲学思想。为了支持这种通用...

    Linux内核设计与实现_第三版_清晰中文版.pdf

    - **虚拟内存**:Linux内核通过虚拟内存技术实现了物理内存的抽象,使得每个进程拥有独立的地址空间。 - **页面置换算法**:包括LRU(Least Recently Used)、Clock算法等,用于决定哪些页面可以被替换出物理内存。 - ...

    Linux内核设计与实现(第三版中文高清带目录).pdf.zip

    2. **内存管理**:Linux内核采用分页内存管理,讲解了虚拟内存的概念,如何将物理内存映射到虚拟地址空间,以及如何进行内存分配和回收,包括交换机制和内存碎片的优化。 3. **文件系统**:文件系统是操作系统的...

    《《操作系统:设计与实现》》

    设备分类通常分为块设备(如硬盘)和字符设备(如键盘、打印机),对应的I/O控制方式有中断驱动I/O、DMA(直接内存访问)和轮询I/O等。 书中还可能涉及操作系统的设计模式,如微内核、宏内核、混合内核等,以及并发...

    LINUX内核设计与实现

    3. **内存管理**:Linux内核通过虚拟内存系统实现高效内存利用。它包括页表、页缓存、交换机制等,使得进程可以独立地访问内存空间,同时保持数据的一致性和安全性。 4. **文件系统**:Linux内核支持多种文件系统,...

    ORANGE’S:一个操作系统的实现,oranges一个操作系统的实现 下载,C,C++

    4. 内存管理:操作系统如何分配、回收内存,以及如何实现虚拟内存技术,如分页和分段。这将涉及物理地址与逻辑地址的转换,以及页面替换算法(如LRU、FIFO等)。 5. 设备驱动程序:操作系统与硬件设备之间的桥梁,...

    Orange's一个操作系统的实现(于渊《自己动手写操作系统第二版》)随书光盘

    中断处理机制使得操作系统能够及时响应硬件事件,如键盘输入、时钟滴答或磁盘I/O完成。中断处理程序会在硬件触发中断时暂停当前进程,保存上下文,然后执行相应的服务例程,最后恢复被中断的进程。 文件系统是操作...

    如何实现Linux与Windows共存 文档

    总结来说,实现Linux与Windows共存的关键在于规划好硬盘分区,理解Linux的文件系统,并在安装过程中谨慎操作。遵循上述步骤,你可以在保留现有Windows系统的同时成功安装RedHat Linux 9.0,享受双系统的便利。

    Linux内核设计与实现

    3. **内存管理**:Linux内核采用虚拟内存系统,通过页表映射物理内存,实现内存保护和内存分段。它还包括内存分配、回收和交换策略。 4. **文件系统**:Linux内核支持多种文件系统,如EXT4、XFS等,文件系统管理...

    ExtAspNet v2.2.1 (2009-4-1) 值得一看

    -如何自定义Javascript脚本和C#处理函数来响应键盘事件。 -为Tree增加AutoLeafIdentification属性。 -增加示例(tree_auto_leaf_identification.aspx)(feedback:wdrabbit)。 +2009-11-17 v2.1.4 -修正...

    orang一个操作系统的实现

    orang's可能实现了页式或段式内存管理,以及虚拟内存技术,以提高内存利用率和程序的隔离性。 3. **进程管理(Process Management)**:操作系统需要管理和调度进程,以保证多个程序的并发执行。orang's可能包含...

    ORANGE’S:一个操作系统的实现(高清晰版PDF)

    虚拟内存技术使得程序可以运行在比实际物理内存更大的地址空间上,而分页和分段机制则允许动态分配和共享内存。 3. **文件系统**:文件系统是操作系统中用于组织和存储数据的一种结构。它定义了文件的命名、存储、...

Global site tag (gtag.js) - Google Analytics