jQuery 实现带下拉提示且自动填充的邮箱

<!-- 本文例子所引用的jQuery版本为 jQuery-1.8.3.min.js -->

 

本文用 jQuery 实现一个用户输入字符时出现能够提示邮箱后缀名的下拉菜单,并且在选择下拉菜单中的邮箱后缀名后可自动填充未完成的输入框,在做这个功能时候,我参考的是网易注册(http://reg.163.com/reg/reg.jsp?product=urs)中的邮箱栏目所实现的功能与效果。这个功能的目的是使用户在填写邮箱栏目的过程中,在带有邮箱后缀名的菜单的提示下,可以不需要完整输入自己的注册邮箱,达到方便、快捷、友好的效果。在做这个功能的时候,需要充分站在使用者的角度,看怎样设计能够最符合通常情况下人们的使用习惯,又怎样设计反而会让用户感到不便。先来看看功能实现的效果图:

 

①初始状态,邮箱栏目未获得焦点时 

  以及 鼠标点击后获得焦点时

 

②以空白字符( space , tab ) 以及@开头时,不出现提示菜单

 

③输入有效字符时,提示下拉菜单出现,用户输入的内容自动添加进菜单,并且第一条提示栏目获得高亮

 

④输入的字符第一次出现"@"时,输入的"@"并不加入提示菜单

 

⑤"@"之后出现有效字符时,就会同提示菜单中的邮件后缀从后缀首尾起进行比较,把和用户输入的邮箱后缀不同的提示从菜单中去掉。同时过滤后的第一条提示获得高亮。在完全匹配之后,下拉菜单隐藏。

 

⑥用户删除邮件输入框中的字符时,呈现的效果顺序是 ⑤图3---> ⑤图2---> ⑤图1---> ④图

 

⑦按下键盘方向键向上或向下使菜单相应提示高亮

 

 ⑧鼠标划过菜单提示时,原先的高亮消失,鼠标划过的栏目获得高亮;鼠标移开,失去高亮

 

⑨点击高亮提示或者高亮处回车,自动填充邮箱元素,选择完成,菜单收起

 

⑩在下拉菜单展开时,鼠标点击页面任何元素,菜单收起

 

注:此功能不包括正则验证邮箱格式。

本功能没有用到什么复杂的知识点,只有简单的JS字符串的匹配 ( match )、位置检索 ( indexOf ) 、截取 ( substr ) 以及jQuery选择器的应用等。更主要的是对功能的逻辑分析要思路清晰,以及思考如何设计能真正使用户操作简便。这个功能的事件主要包括:

 

代码分析:

 HTML和CSS代码

1 <div class="ipt">
2     <input type="text" name="uemail" id="uemail" placeholder="请输入常用邮箱"/>
3     <ul class="autoul"></ul>
4 </div>
View Code
 1 .ipt{ width:218px;}/* 输入框外围div */
 2 input{ margin:0; padding-left:15px; padding-right:15px; width:184px;}/* 输入框 */
 3 ul.autoul{  /* 下拉菜单 */
 4 
 5     width:216px;
 6     margin:0px;
 7     margin-top:-5px;
 8     padding:0px;
 9     color:#666;
10     border:1px solid #666;
11     border-top:0;
12     overflow:hidden;
13 }
14 ul.autoul li.autoli{  /* 下拉菜单li */
15 
16     height:30px;
17     display:block;
18     list-style-type:none;
19     text-align:left;
20     cursor:pointer;
21     font-size:14px;
22     line-height:30px;
23     padding-left:15px;
24     padding-right:15px;
25     overflow:hidden;
26     /*当对象内文本溢出时显示省略标记*/
27     text-overflow:ellipsis; 
28 }
29 .lihover{  /* 下拉菜单li高亮样式 */
30 
31     background-color:#eee;
32 }
33 span{ padding-right:2px;}/* li下文字 */
34 .showli{ display:block;}/* 经过过滤的li的样式 */
View Code

 

 在DOM加载完毕后,初始化邮件列表并隐藏下拉菜单,JS代码片段:

 1 $(function(){
 2 
 3     //初始化邮箱列表
 4     var mail = new Array("sina.com","126.com","163.com","gmail.com","qq.com","vip.qq.com","hotmail.com","sohu.com","139.com","vip.sina.com","21cn.cn","189.cn","sina.cn");
 5 
 6     //把邮箱列表加入下拉
 7     for(var i=0;i<mail.length;i++){
 8     
 9         var $liElement = $("<li class=\"autoli\"><span class=\"ex\"></span><span class=\"at\">@</span><span class=\"step\">"+mail[i]+"</span></li>");
10 
11         $liElement.appendTo("ul.autoul");
12     }
13 
14     //下拉菜单初始隐藏
15     $(".autoul").hide();
16     
17     //其他事件..........
18 });

 

 输入框$("#uemail")的keyup事件是该功能的主要事件,之所以用keyup事件而不用keydown事件是因为keyup事件在用户将键盘按键抬起时触发,是整个按键动作的最后阶段,所以在抬起按键时能看到相应的动作;而使用keydown事件时,只有在下一次按下键盘按键时才能看到上一次按下按键触发的动作,所以keydown事件在通过键盘获得页面控制方面用的比较多。但是keyup事件不能实现按下小键盘上下方向键不放时依然能快速选择下拉提示菜单的提示,算是这个功能的一个不完美的地方,而网易的邮箱栏能做到这一点。

1 //在邮箱输入框输入字符
2 $("#uemail").keyup(function(){
3 
4       //........
5 })

 

邮件输入框$("#uemail")的keyup事件中,有以下几种情况需要考虑:

①有输入的按键,使输入框有长度( 因为删除事件也是判断匹配以及长度,所以只需要添加删除事件特有的动作,而不必在此处排除删除事件 )

 

 1             //菜单展现,需要排除空格开头和"@"开头
 2             if( $.trim($(this).val())!="" && $.trim(this.value).match(/^@/)==null ) {
 3 
 4                 $(".autoul").show();
 5                 //同时第一条提示高亮
 6                 $(".autoul li:visible:eq(0)").addClass("lihover");
 7             }else{//如果为空或者"@"开头
 8                 $(".autoul").hide();
 9                 $(".autoul li:eq(0)").removeClass("lihover");
10             }
11 
12             //把输入的字符填充进提示,有两种情况:1.出现"@"之前,把"@"之前的字符进行填充;2.出现第一次"@"时以及"@"之后还有字符时,不填充
13             //出现@之前
14             if($.trim(this.value).match(/[^@]@/)==null){//输入了不含"@"的字符或者"@"开头
15 
16                 if($.trim(this.value).match(/^@/)==null){
17                     //不以"@"开头
18                     $(this).next().children("li").children(".ex").text($(this).val());
19                 }
20             }else{
21 
22                 //输入字符后,第一次出现了不在首位的"@"
23                 //当首次出现@之后,有2种情况:1.继续输入;2.没有继续输入
24                 //当继续输入时
25                 var str = this.value;//输入的所有字符
26                 var strs = new Array();
27                 strs = str.split("@");//输入的所有字符以"@"分隔
28                 $(".ex").text(strs[0]);//"@"之前输入的内容
29                 var len = strs[0].length;//"@"之前输入内容的长度
30                 if(this.value.length>len+1){
31 
32                     //截取出@之后的字符串,@之前字符串的长度加@的长度,从第(len+1)位开始截取
33                     var strright = str.substr(len+1);
34 
35                     //正则屏蔽匹配反斜杠"\"
36                     if(strright.match(/[\\]/)!=null){
37                         strright.replace(/[\\]/,"");
38                         return false;
39                     }
40 
41                     //遍历li
42                     $("ul.autoul li").each(function(){
43 
44                         //遍历span
45                         //$(this) li
46                         $(this).children("span.step").each(function(){
47 
48                             //@之后的字符串与邮件后缀进行比较
49                             //当输入的字符和下拉中邮件后缀匹配并且出现在第一位出现
50                             //$(this) span.step
51                             if($("ul.autoul li").children("span.step").text().match(strright)!=null && $(this).text().indexOf(strright)==0){
52                                 //class showli是输入框@后的字符和邮件列表对比匹配后给匹配的邮件li加上的属性
53                                 $(this).parent().addClass("showli");
54                                 //如果输入的字符和提示菜单完全匹配,则去掉高亮和showli,同时提示隐藏
55                                 if(strright.length>=$(this).text().length){
56                                     $(this).parent().removeClass("showli").removeClass("lihover").hide();
57                                 }
58                             }else{
59                                 $(this).parent().removeClass("showli");
60                             }
61                             if($(this).parent().hasClass("showli")){
62                                 $(this).parent().show();
63                                 $(this).parent("li").parent("ul").children("li.showli:eq(0)").addClass("lihover");
64                             }else{
65                                 $(this).parent().hide();
66                                 $(this).parent().removeClass("lihover");
67                             }
68                         });
69                     });
70                 }else{
71                     //"@"后没有继续输入时
72                     $(".autoul").children().show();
73                     $("ul.autoul li").removeClass("showli");
74                     $("ul.autoul li.lihover").removeClass("lihover");
75                     $("ul.autoul li:eq(0)").addClass("lihover");
76                 }
77             }
78         }//有效输入按键事件结束

 

②按键为backspace(8)或是delete(46)

1 if(event.keyCode == 8 || event.keyCode == 46){
2 
3      $(this).next().children().removeClass("lihover");
4      $(this).next().children("li:visible:eq(0)").addClass("lihover");
5 }//删除事件结束

 

③按键为方向键↓(40)

 1 if(event.keyCode == 40) {
 2 
 3             //当键盘按下↓时,如果已经有li处于被选中的状态,则去掉状态,并把样式赋给下一条(可见的)li
 4             if ($("ul.autoul li").is(".lihover")) {
 5 
 6                 //如果还存在下一条(可见的)li的话
 7                 if ($("ul.autoul li.lihover").nextAll().is("li:visible")) {
 8 
 9                     if ($("ul.autoul li.lihover").nextAll().hasClass("showli")) {
10 
11                         $("ul.autoul li.lihover").removeClass("lihover")
12                                                  .nextAll(".showli:eq(0)").addClass("lihover");
13                     } else {
14 
15                         $("ul.autoul li.lihover").removeClass("lihover").removeClass("showli")
16                                                  .next("li:visible").addClass("lihover");
17                         $("ul.autoul").children().show();
18                     }
19                 } else {
20 
21                     $("ul.autoul li.lihover").removeClass("lihover");
22                     $("ul.autoul li:visible:eq(0)").addClass("lihover");
23                 }
24             }
25 }//方向键↓结束

 

④按键为方向键↑(38)

 1 if(event.keyCode == 38){
 2 
 3             //使光标始终在输入框文字右边(不完美 ①只有在keyup事件中起作用,keydown不行 ②向上时光标每次先移到最左,然后再移到最右)
 4             $(this).val($(this).val());
 5 
 6             //当键盘按下↓时,如果已经有li处于被选中的状态,则去掉状态,并把样式赋给下一条(可见的)li
 7             if($("ul.autoul li").is(".lihover")){
 8 
 9                 //如果还存在上一条(可见的)li的话
10                 if($("ul.autoul li.lihover").prevAll().is("li:visible")){
11 
12 
13                     if($("ul.autoul li.lihover").prevAll().hasClass("showli")){
14 
15                         $("ul.autoul li.lihover").removeClass("lihover")
16                                 .prevAll(".showli:eq(0)").addClass("lihover");
17                     }else{
18 
19                         $("ul.autoul li.lihover").removeClass("lihover").removeClass("showli")
20                                 .prev("li:visible").addClass("lihover");
21                         $("ul.autoul").children().show();
22                     }
23                 }else{
24 
25                     $("ul.autoul li.lihover").removeClass("lihover");
26                     $("ul.autoul li:visible:eq("+($("ul.autoul li:visible").length-1)+")").addClass("lihover");
27                 }
28             }else{
29 
30                 //当键盘按下↓时,如果之前没有一条li被选中的话,则第一条(可见的)li被选中
31                 $("ul.autoul li:visible:eq("+($("ul.autoul li:visible").length-1)+")").addClass("lihover");
32             }
33 }//方向键↑结束

 

⑤按键为回车键(13)

 1 if(event.keyCode == 13){
 2 
 3             if($("ul.autoul li").is(".lihover")) {
 4 
 5                 $("#uemail").val($("ul.autoul li.lihover").children(".ex").text() + "@" + $("ul.autoul li.lihover").children(".step").text());
 6             }
 7 
 8             $(".autoul").children().hide();
 9             $(".autoul").children().removeClass("lihover");
10 }

至此按键事件结束。

 

⑥当鼠标点击下拉菜单的具体一条内容时

1 $(".autoli").click(function(){
2     
3         $("#uemail").val($(this).children(".ex").text()+$(this).children(".at").text()+$(this).children(".step").text());
4         $(".autoul").hide();
5 });
6     //鼠标点击下拉菜单具体内容事件结束

 

⑦当鼠标点击document时,下拉隐藏

1 $("body").click(function(){
2     
3         $(".autoul").hide();
4 });
5 //鼠标点击document事件结束

 

⑧鼠标划过li时

 1 $("ul.autoul li").hover(function(){
 2 
 3         if($("ul.autoul li").hasClass("lihover")){
 4 
 5             $("ul.autoul li").removeClass("lihover");
 6         }
 7         $(this).addClass("lihover");
 8     },function(){
 9 
10         $(this).removeClass("lihover");
11 });

 至此,功能完成。最终的功能演示如下:

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。