jQuery插件–小工具回车触发联动事件

在前端的技术中,联动是一个很常见又很重要的功能,它可以让我们的操作变得更简单,比如当我们以enter键提交信息,鼠标悬浮显示二级菜单等,都是属于联动的操作。所以,最近基于jQuery写了一个小的模块,我觉得应该是中间件吧,这里只实现逻辑的处理,至于触发之后的逻辑业务层,需要根据不同的输入值,进行不同的处理。

一:概述

我个人非常喜欢的插件或者说模块,是那种完全不和业务逻辑挂钩的那种,当我使用这样的插件时,所有的业务逻辑,以及属性动作,都是我传入的参数进行控制的,因为我觉得这样,我写的代码,更受我自己的控制,也可以更多的应用到其他地方,并且,当业务逻辑进行更改时,我可以放心的修改对应的逻辑模块,而不必担心这些修改,会影响到其他使用该模块的业务部分,这样会使得代码的耦合性,更低一些吧。也会使得代码逻辑,更具有层次,对于阅读和理解,修改等,都有更好的可维护性等。

我觉得吧,关键是层次更分明。语言表达有限~~

二:回车触发

想必大家应该都喜欢在聊QQ的时候,使用enter键发送消息吧,而不是使用鼠标点击“发送”按钮进行消息的发送,因为使用enter键可以非常节省我们的时间和操作步骤,简单点说,手本来在键盘上,去点击发送,不是还得让手离开键盘,去拿鼠标么~~~

所以,在很多时候,前端的展示页面中,也是会经常碰到这样的状况的,需要以回车键还执行一些动作,比如:现在需要一个小功能,点击一个按钮,显示一个输入框中已经输入的值:最简单的代码了,就不直接添加demo页面了,这里直接给出代码就行了吧。


<div>
    <label for = "test" ><input type = "text" id = "test" /><button id = "getText">getText</button></label>
</div>


上面的只是HTML部分的代码,下面添加相应的JS动作:


var test = $("#test"),
    getText = $("#getText");
	
getText.on("click",function(){
    var text = $.trim(test.val()) || "";
    text && alert(text);
});


当前,虽然觉得是废话,还得说一句,记得引入jQuery文件。

这样,就有一个最简单的示例了,当点击getText按钮,就会弹出输入框中已有的值,如果没有输入或者输入框为空,则弹出值。

可是这个时候,我们需要添加一个功能,当再输入框输入信息完成之后,在键盘上按下enter键,也可以弹出已输入的值呢。

这个只是,就不得不进行如下的修改,在上述JS的基础上,添加如下的JS


test.on("keydown",function(e){
    e = e || window.event;
    var code = e.which || e.keyCode;
		
    if(code == 13){
	getText.trigger("click");
    }
});


可是,这个时候,我希望只是在按下enter键时,才触发,而当同时按下ctrlaltshift时,就不再触发这个事件了,所以,上述的代码又得重新做一些修改,我们都知道,ctrlaltshift这三个功能键是否被按下的信息,是保存在event对象中的,所以,我们就可以对上述代码进行如下的更改:


test.on("keydown",function(e){
    e = e || window.event;
	
    var code = e.which || e.keyCode;
	
    if(code == 13 && !e.altKey && !e.ctrlKey &&!e.shiftKey){
	getText.trigger("click");
    }
});


到这里,我就会觉得,我这个人,到底是有些强迫症还是有些洁癖的问题了,因为上面的代码,其实已经可以完成我们需要的功能了,但是,在if的判断时,当按下的时enter时,需要执行4个判断。。。才能确认,是只按下了enter键。

所以,这个时候,我就会想着把if中的判断条件进行更改,以执行尽量少的判断,所以我就会想要把上述的代码,变化成下面的情况:


test.on("keydown",function(e){
    e = e || window.event;
	
    var code = e.which || e.keyCode;
	
    if(!(code != 13 || e.altKey || e.ctrlKey || e.shiftKey)){
	getText.trigger("click");
    }

});


但是这个时候呢,就会再想一个问题,之前用“&&”的方法,当不是按下enter键时,只需要一个判断即可,而使用“||”时,就需要两次,而在每次在键盘上,按下键盘时,按下enter的概率又是多少呢?

有些扯淡了,这个其实也算是没有什么的,因为这样的问题,也不需要这些考虑吧,如果真是要考虑,还得考虑对象中读取属性,和逻辑操作,那种情况更有效率呢,想多了~~~

OK,代码的逻辑方面的问题,就到这里了,那么问题又来了,如果我一个页面中,需要多次这样的逻辑呢,难道要这样复制很多次么?即占用空间,又不好维护,所以,还是把这些东西直接以一个模块的形式保存,在想要使用的元素上,只需要调用该模块即可。

三:回车触发的模块化

经过上述的讨论,就可以完成如下一个用于enterTrigger的功能模块:


$.extend({
    //判断目标对象obj是否为jQuery对象
    isjQuery:function(obj){
	return obj instanceof jQuery;
    },
	
    //很多时候,当我们点击回车时,会触发其他的一些事件。
    enterTrigger:function(obj,src,type){
	if(!$.isjQuery(obj)){
	    obj = $(obj);
	}
	if(!$.isjQuery(src)){
	    src = $(src);
	}
		
	if(!obj.size() || !src.size()){
	    return false;
	}
		
	type = type || "click";
		
	obj.on("keydown",function(e){
	    e = e || window.event;
	    var code = e.which || e.keyCode;
			
	    if(!(code != 13 || e.altKey || e.ctrlKey || e.shiftKey)){
		src.trigger(type);
	    }
	});
	return this;
    }
});


这个时候,之前我们测试时的代码,就可以更简单化的实现这个功能了。


$.enterTrigger(test,getText,"click");
//$.enterTrigger(test,getText);
//如果是使用click事件触发,甚至可以省略掉第三个参数。


因为此时的enterTrigger只是定义到了jQuery的对象中,并没有定义到jQuery对象的原型链中,所以也可以使用下面的方法,把enterTrigger添加到jQuery的原型链中去。这样,每一个jQuery的实例,都可以使用链式操作来实现该功能了,可以通过如下的方法,把enterTrigger方法,添加到原型链中去:


$.fn.extend({
    enterTrigger:function(src,type){
	return $.enterTrigger($(this),src,type);
    }
});


当你添加了上述的方法在原型链中,那么就可以使用如下的方法,来添加这个模块了。


test.enterTrigger(getText,"click");


这样的方法,也是我们在jQuery中,最常用的的使用方法了吧,看着更顺眼一点呗。

上述的方法,基本上已经满足了我们的正常需求了吧,但是有时候,如果我们的需求进行少量的修改呢?比如,我需要在按下ctrl+enter时,才执行这个方法?

这是个简单的需求,也是个常用的需求吧,那么看下面怎么实现吧,先实现代码如下:


$.extend({
    //判断目标对象obj是否为jQuery对象
    isjQuery:function(obj){
	return obj instanceof jQuery;
    },
	
    //很多时候,当我们点击回车时,会触发其他的一些事件。
    enterTrigger:function(options){
	/*
	 * obj 目标元素
	 * src obj元素按下enter时,触发src中的type类型的事件
	 * type src元素将被触发的事件类型
	 * needCtrl 是否需要按下ctrl,默认为false,
	 * needAlt 是否需要按下alt键,默认为false,
	 * needShift 是否需要按下shift键,默认为false
	 * 上述三个,当委托ture时,表示ctrl+enter等联合的时,才能触发
	*/
	if(!$.isjQuery(options.obj)){
	    options.obj = $(options.obj);
	}
	if(!$.isjQuery(options.src)){
	    options.src = $(options.src);
	}
		
	if(!options.obj.size() || !options.src.size()){
	    return false;
	}

	options.type = options.type || "click";
		
	options.needCtrl = options.needCtrl || false;
	options.needAlt = options.needAlt || false;
	options.needShift = options.needShift || false;
	options.obj.on("keydown",function(e){
	    e = e || window.event;
	    var code = e.which || e.keyCode,
		flag = code == 13,
		altKey = false,
		ctrlKey = false,
		shiftKey = false;
				
	    if(flag){
		//这个时候,判断是否需要altKey键
		altKey = e.altKey;
		flag = options.needAlt?altKey:!altKey;
	    }
			
	    if(flag){
		//这个时候,判断是否需要ctrlKey键
		ctrlKey = e.ctrlKey;
		flag = options.needCtrl?ctrlKey:!ctrlKey;
	    }
			
	    if(flag){
		//这个时候,判断是否需要shiftKey键
		shiftKey = e.shiftKey;
		flag = options.needShift?shiftKey:!shiftKey;
	    }

	    if(flag){
		options.src.trigger(options.type);
	    }
	});
		
	return this;
    }
});


$.fn.extend({
    enterTrigger:function(options){
	var obj = options;
	obj.obj = $(this);
	return $.enterTrigger(obj);
    }
});


关于这个修改之后的操作,请以下面的页面可以进行测试:

源文件地址:demo

OK,就这么结束吧,一个小的插件,很简单但有用的哦。

一个这么简单的东西,竟然也bala这么多~~

如有疑问,请指教!

本文地址: http://www.zhangyunling.com/?p=261

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>