如何制作好一个提交按扭---我是个爱折腾的人
最近在修改一个MVC项目的页面时要实现输入为空时禁用提交按扭的功能,这其实是个很简单的功能,这里只是写点自己的分享出来,顺便总结经验以后查用。资深专家勿喷 。
在制作表单时,我们经常会遇到需要对表单内容进行验证,数据非法时不允许用户提交。对用户的输入进行验证又有两种选择:服务器端的验证和客户端的验证。由于后者会重大服务器的负担,不利于服务器处理更为核心的业务,一般我们都选择用JavaScript在客户端进行验证。这样会保证数据在送达服务器时已经是正确的,减轻了服务器开销,更重要的是,客户端的验证是即时的,不会存在与服务器进行通信的时间开销。
如果你在开发中使用的是第三方控件,你可能不必考虑验证了,控件大都自带了数据验证功能,你只需调用相关功能即可。但很多时候其实还是需要我们亲自动手进行验证的。
输入为空禁用提交按扭
当输入框中没有值时,无聊的用户还是会猛击提交按扭的,这时需要将提交禁用掉。即使是这样一个灰常之简单的功能,在初次尝试时也不是一下就达到了我想要的效果的,寻求理想的解决方案是个过程。这里我将用jQuery来实现。
首先构造一个非常简单的页面,只是用来演示,上面放一个输入框,一个提交按扭。
下面打开VS2010新建一个网站项目(当然,本文中的一切操作你完全可以在记事本中完成,我只是想用VS的代码提示及排版方便些)
图1
然后右击项目名选择添加新项,往项目中添加一个HTML 页面。
往上面放面放一个输入框和一个提交按扭。<body>部分代码如下:
1 <body> 2 <input type="text" id="name"/> 3 <input type="submit" id="submit"/> 4 </body>
出来的页面应该是这样的
图2
为了使用jQuery,需要将jQuery引用到这个页面中,在新建网站项目时VS已经把jQuery放在了Scripts文件夹中,我们只需在页面的<head>部分添加对jQuery的引用。
1 <script type="text/javascript" src="Scripts/jquery-1.4.1.js"></script>
现在点击提交还没有任何反应,现在我们为提交按扭添加一个方法,好在点击提交之后执行些什么。我们让页面弹出个消息框,对输入框中输入的名字问好。
还是在<head>部分,我们添加如下代码:
1 <script> 2 3 $(document).ready(function() { 4 5 $("#submit").click(function() { 6 7 alert("Hello," + $("#name").val()); 8 9 }); 10 11 }); 12 13 </script>
如果不熟悉jQuery,你可能需要简单学习一下,不过上手很快。Ready()表示页面元素加载完成之后,再执行ready里面的function()。现在我们点击提交会弹出一个消息框,如果我们输入了值的话,消息框中的Hello会加上我们的输入。
图3
图4
上面看到,即使没有输入,提交也会成功,现在来增加对输入是否为空的验证。
考虑到页面第一次加载后,输入框中并没有输入,所以一开始我们就需要把提交禁用掉。所以我的基本思路是取到输入框中的值,如果有输入,这个值的长度肯定大于0,把提交按扭的disable属性去掉,让用户可以提交,如果没有输入,这个值的长度等于0,则什么也不做。
所以我们在$(document).ready()增加一个方法,代码如下:
1 <script> 2 3 $(document).ready(function () { 4 5 $("#submit").attr("disabled", "disabled"); 6 7 $("#name").change(function () { 8 9 if ($(this).val().length > 0) { 10 11 $("#submit").removeAttr("disabled"); 12 13 } 14 15 }); 16 17 $("#submit").click(function () { 18 19 alert("Hello," + $("#name").val()); 20 21 }); 22 23 }); 24 25 </script>
打开页面后,第5行的代码将提交按扭禁止。然后第7行的change方法监听输入框中值的变化,如果变化,则进行长度判断,大于0说明有输入,移除掉提交按扭的disable属性使其能用。否则表示没有输入,什么也不做。
图5
我们输入东西进去然后单击页面空白部分使焦点离开输入框这时提交按扭可用,弹出了图4一样的消息框,工作正常。
但如果我们把刚才的输入擦掉,再点击,还是可以弹出消息框,说明程序不完善。这是因为第一次输入之后,程序判断有值,那么就把提交按扭激活了,到第二次清空输入后再点击提交时,按扭依然是激活的,所以出现这种情况。
于是我们$("#submit").click()方法进行一下修改,在提交时进行判断,如果有输入,则正常弹出消息框,如果没有输入,则不弹出,并且我们让输入框获得焦点,提示用户进行输入。
1 $("#submit").click(function () { 2 3 if ($("#name").val().length > 0) { 4 5 alert("Hello," + $("#name").val()); 6 7 } else { 8 9 $("#name").focus(); 10 11 } 12 13 });
再次运行,输入之后,单击页面其他空白处激活按扭,再将输入清空,这时再点击提交,不会弹出消息框了。到这里,不管完不完美,想要的输入为空禁用提交功能是实现了。
上面为了激活提交按扭,我们输入之后还需单击页面其他部分让焦点从输入框离开,这确实有点不爽。这里激活提交是调用的change方法,而输入框的change方法只有在输入框失去焦点后才会触发,这就是为什么总需要点击页面其他地方让光标离开输入框。
完美的情况应该是我们一旦输入了东西,按扭就自动激活,而不需要我们再去点其他地方。这时你可能会想到用keydown(),keyup(),或者keypress()这样的方法来代替change(),这些方法确实可以。但仍会有些小问题。这里我们试一下用keydown()来代替change()。现在变成只要输入框中有键按下,就会判断到有值输入从而激活提交按扭。
1 $(document).ready(function () { 2 3 $("#submit").attr("disabled", "disabled"); 4 5 $("#name").keydown(function () { 6 7 if ($(this).val().length > 0) { 8 9 $("#submit").removeAttr("disabled"); 10 11 } 12 13 }); 14 15 $("#submit").click(function () { 16 17 if ($("#name").val().length > 0) { 18 19 alert("Hello," + $("#name").val()); 20 21 } else { 22 23 $("#name").focus(); 24 25 } 26 27 }); 28 29 });
程序运行后,我们发现,在按下第一个字母后,提交按扭还是不可用,在按下第二个字母后,它才变得可用。这是不是黑奇怪!?
对丫,我也觉得黑奇怪。特么神奇了。
图6 图7
仔细分析就会发现问题。keydown是在键被按下的时候触发事件,而刚按下时,键值还没有被输入到框中,所以此刻的输入框中长度确实为0,激活按扭的语句没有没有被执行到;而当我们按第二个键时,因为前面已经输入了一个字符,所以这回同样是在按下的瞬间,检测到框中有值长度为1,所以if语句判断通过,将提交按扭的disable去掉从而激活。另外,keypress()也有同样的问题,原因也是一样的,事件触发时值还没有被输入。还好,最后发现keyup()是可以的。keyup之所以可以是因为它是在按完键弹起后才触发事件,键都弹起了,值肯定已经被输入到框里面去了嘛,所以此刻触发if语句进行判断时,就会得到长度为1。下面是使用keyup()代替change()时的截图,注意,在输入第一个字母后,光标还在输入框中,但按扭已经激活,没有出现上面keydown()和keypress()一样的问题了。
图8
说明keyup()能满足我们的需求,但再仔细一想,用户输入难道必需要按键么,完全可以通过鼠标右击然后粘贴,这在填表单时是经常发生的事。这里我试验了一下,通过鼠标右键粘贴了东西到输入框后,这个看似能解决问题的keyup()也挂掉了,提交还是没有自动激活,需要我们点击其他地方来移除焦点。
图9
后来我研究了一下,还是找到了一个完美的解决办法,那就是用bind()来将我们要做的操作绑定到这个输入框。
最后修改的代码如下:
1 <script type="text/javascript" language="javascript"> 2 3 $(document).ready(function () { 4 5 $("#submit").attr("disabled", "disabled"); 6 7 $("#name").bind("input", function () { 8 9 if ($("#name").val().length > 0) { 10 11 $("#submit").removeAttr("disabled"); 12 13 } 14 15 }); 16 17 $("#submit").click(function () { 18 19 if ($("#name").val().length > 0) { 20 21 alert("Hello," + $("#name").val()); 22 23 } else { 24 25 $("#name").focus(); 26 27 } 28 29 }); 30 31 }); 32 33 </script>
现在,不管你是手动输入,还是Ctrl+V或者鼠标右键的粘贴,提交按扭都能在第一时间被激活。
错误提示---增加用户友好度
为了更人性化,当用户在没有输入任何东西试图提交时,我们应该给点提示信息告诉用户要输入,上面仅仅把焦点转回输入框还是不足不够直观的。
我们在页面上加一个<p>标签来放提示信息:
1 <body> 2 3 <input type="text" id="name" /> 4 5 <input type="submit" id="submit" /> 6 7 <br /> 8 9 <p id="error_msg" style="color: red"> 10 11 u kidding me? input something first!</p> 12 13 </body>
平时让它处于隐藏状态,只有当用户没有输入而试图提交时,才将它显示出来。并且在用户输入之后,提示信息应该立即消失。修改后的js代码如下:
1 <script type="text/javascript" language="javascript"> 2 3 $(document).ready(function () { 4 5 $("#error_msg").hide(); 6 7 $("#submit").attr("disabled", "disabled"); 8 9 $("#name").bind("input", function () { 10 11 if ($("#name").val().length > 0 ) { 12 13 $("#error_msg").hide(); 14 15 $("#submit").removeAttr("disabled"); 16 17 } 18 19 }); 20 21 $("#submit").click(function () { 22 23 if ($("#name").val().length > 0) { 24 25 alert("Hello," + $("#name").val()); 26 27 } else { 28 29 $("#name").focus(); 30 31 $("#error_msg").show(); 32 33 } 34 35 }); 36 37 }); 38 39 </script>
运行效果:
图10
Ctrl+Enter组合键—锦上添花
在输入完登陆的用户名及密码后,你是否试过不去点击“登陆”而直接按ctrl+enter键优雅而便捷地完成登陆,这个组合键也经常用在提交评论。我是觉得这样的用户体验是非常棒的,因为你在完成输入或者帖子的评论后,要把手移开键盘去用鼠标然后再移到相应的按扭上操作,这是很不爽的事。而直接按ctrl+enter提交会便捷得多,至少如果在提供了这样的功能的网站上,我不会用鼠标去提交。
而且一般大企业的网站这方面的细节做得比较好,都有这样的功能。比如你在QQ空间评论好友的说说,可以按ctrl+enter提交。并且这个功能不是很难,只是几句代码的事,我简直找不到理由不去实现它。
只需要再加一个ctrl+enter组合键的监听即可,如果监听到了用户输入同时按下ctrl和enter,则执行提交,这与鼠标点击“提交”的效果是一样的。
这里需要用到jQuery提供的bind()方法。Bind()方法允许你将多个事件绑定到同一个页面元素上,这里我们的绑定目标是输入框。这也是在上面的讨论中什么最后选择了bind()的原因,不仅解决了上面遇到的那些问题,也是为了向输入框再绑定一个事件,一举两得。
原先绑定的”input”部分需要作一下小小的调整,修改后的代码如下:
1 <script type="text/javascript" language="javascript"> 2 3 $(document).ready(function () { 4 5 $("#error_msg").hide(); 6 7 $("#submit").attr("disabled", "disabled"); 8 9 $("#name").bind({ 10 11 input: function () { 12 13 if ($("#name").val().length > 0) { 14 15 $("#error_msg").hide(); 16 17 $("#submit").removeAttr("disabled"); 18 19 } 20 21 }, 22 23 keydown: function (e) { 24 25 if (e.ctrlKey && e.keyCode == 13) { 26 27 $("#submit").click(); 28 29 } 30 31 } 32 33 }); 34 35 $("#submit").click(function () { 36 37 if ($("#name").val().length > 0) { 38 39 alert("Hello," + $("#name").val()); 40 41 } else { 42 43 $("#name").focus(); 44 45 $("#error_msg").show(); 46 47 } 48 49 }); 50 51 }); 52 53 </script>
键盘上每个按键都对应着一个数字编码,代码中的e.keyCode == 13指的正是enter键。关于按键编码可以参考这里。
给提交按扭变个样
现在的提交按扭还只是系统提供的默认样式,为了美观,我们可以通过定义CSS 样式来进行简单美化一下。至少做到按扭换个好看点的,并且在鼠标放上去时可以变个颜色。
同样在<head>部分,我们定义一下style。其中按扭要用到的图片可以在网上找,也可以下载文章末尾的源码,里面包含了图片。
更改后的代码如下:
1 <style type="text/css"> 2 3 #submit 4 5 { 6 7 width: 85px; 8 9 height: 30px; 10 11 line-height: 30px; 12 13 background: url(btn.gif) top center no-repeat; 14 15 border: 0; 16 17 font-family: "Titillium800" , "Trebuchet MS" , Arial, sans-serif; 18 19 font-size: 14px; 20 21 font-weight: normal; 22 23 text-transform: uppercase; 24 25 color: white; 26 27 text-shadow: 1px 1px 0 #0A5482; 28 29 cursor: pointer; 30 31 margin-right: 10px; 32 33 vertical-align: middle; 34 35 } 36 37 #submit:hover 38 39 { 40 41 background: url(hover.gif) top center no-repeat; 42 43 text-shadow: 1px 1px 0 #b55f10; 44 45 } 46 47 48 49 #name 50 51 { 52 53 height: 25px; 54 55 } 56 57 </style>
现在可以看到,我们的页面是这样的了。
图11 图12
只接受特定类型的输入
进行到这里,仔细思考会觉得,我为什么允许用户能够输入非法值,然后再煞费苦心地去验证,完了再输出友情提示:亲,你的输入是非法的,这样不好~我们完全可以将输入框设置为只能输入我们想要的数据类型,这就是最小用户假设。我们不愿去承担处理非法输入的开销,我们假设用户只输入我们指定的类型,比如在一个前面指名了年龄的输入框中,按常识用户当然知道这里需要输入的是数字而且必需是正整数!所以在这样的输入框里我们只接受数字,确切地说是正整数,如果用户试图输入字母或者狂砸键盘,只有数字才会被输入到输入框中。
这里,因为是名字输入框,应该设置为不接受数字类型及其他特殊符号的输入,即只接受a-z,A-Z以前中文字符。
这个时候,就是正则表达式强大功能得到体现的时候了。如果你不熟悉正则表达式,你可能需要简单的学习下,上手同样很快。
首先在HTML标签中为输入框添加onkeypress事件,并指定事件触发后的处理器。如下:
1 <input type="text" id="name" onkeypress='validate(event)'/>
然后我们在<javascript>部分来实现这个validate(event)方法,它带有一个参数,即事件的发送者。紧接着$(document).ready(),我们添加对validate的实现:
1 function validate(evt) { 2 3 var theEvent = evt || window.event; 4 5 var key = theEvent.keyCode || theEvent.which; 6 7 key = String.fromCharCode(key); 8 9 var regex = /[a-zA-Z]|\./; 10 11 if (!regex.test(key)) { 12 13 theEvent.returnValue = false; 14 15 if (theEvent.preventDefault) theEvent.preventDefault(); 16 17 } 18 19 }
最后,我们运行程序测试一下效果。当我们试图输入数字时,数字不会上屏,输入框中没有任何变化,我们换字母或者汉字时,才能正常输入。
但测试还发现,换成中文输入法时,好多符号也能输入。说明这里的正则表达式还是有缺陷的,但至少我们屏蔽掉了数字的输入。
如果你有更好的方法来实现这一部分,请指教,请跟进,共同学习。
后记:看似简单的一个提交功能,我觉得要做好还是需要花一些时间来掌握的。这里好多地方也都还有不足,比如文章最后一部分“只接受特定类型的输入”,可能面临很多不两只的需求,这里可能只需要金钱类型的格式,另外一个地方要求只能输入喵星语汪星语,所以不同情况,这里的实现会有不同,但正则表达式会是一个很好很强大的选择。
可以参考的文章
1.关于jQuery.bind()方法
2.ctrl+enter combo key
http://stackoverflow.com/questions/1684196/ctrlenter-jquery-in-textarea
3.Binding Multiple Event Handlers
http://www.peachpit.com/articles/article.aspx?p=1371947&seqNum=3
4.Numeric input
http://stackoverflow.com/questions/469357/html-text-input-allow-only-numeric-input
5.keycode
http://www.expandinghead.net/keycode.html