打造基于jQuery的智能选择输入框

UPDATE:修正了在FireFox下显示的问题,从新copy CSS便可javascript

写完这个名字突然以为有点标题党的嫌疑,可是又不知道什么样的名字比较合适,那就暂且这样吧。css

今天要讲的东西比较简单,其中会用到另外的一个jQuery控件,是一我的员选择输入框。那究竟是个什么东西呢?
那好仍是先来看最后的效果,有个直接的了解。html

 image

 

是否是和时下流行的SNS网站的选择人员控件很像?对比一下,哈哈是的,其实目的是差很少的。java

image

其实还有不少这样应用,如邮件系统中发件人,在输入时的自动补全,它是一个相似于Autocomplete的功能,可是又要比Autocomplete多那么一些功能的插件jquery

基于这个状况,我所编写的这个控件时基于一个Autocomplete控件的,它就是jQuery.autocomplete,它的官方网址是:http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/数据库

你们能够经过访问如下来获取它的使用方法,资料和demo仍是比较详细,我这边就不重复写了。因此咱们仍是直接开始扩展的部分数组

第一咱们仍是先肯定HTML缓存

从html上分析autocomplete和选人控件的所查的就是服务器

1:外侧的容器 2:选中的人员的那个小方块imagemvc

容器咱们用Div就能够了,小方块也比较简单 ,来看一下,最外层是div包裹,而后是嵌套一个a标签(为了方便之后作hover效果),在a标签中是一个span放置文字,

input[type=hidden]来防止这个节点的数据,img就彷佛删除按钮的载体,那控件的载体又是什么呢?其实从设计来讲能够是个input的,可是我更偏向于div,在实例化的时候往div中动态添加一个input来附加autocomplete的属性,若是反过来在input外包裹容器的话,在一些特殊状况下定位会是问题。

image

那html既然已经定义好了,接着就是CSS了,这个css其实很简单,就是容器的边框还有就是item的样子而已,来看下代码

本例中只有使用一个图片 del

第二 开始编写Javascript

仍是老规矩,先来个完整代码,很是简单只有不到70行代码

接着咱们来一步一步来分析个人实现,开始仍是编写jQuery控件的“模板”,关于为何要这么写,请参考这篇的说明

?
1
2
3
4
5
6
7
8
; ( function ($) {
     if (!$.Autocompleter) {
         alert( "请先引用jquery.autocomplete.js" );
         return ;
     }
    $.fn.usbox = function (o) {
    }
})(jQuery)
此次加了一个判断,由于咱们这个控件是依赖于autocomplete的,若是你看了前两篇,那么就必定知道接着就是编写默认参数
1
2
3
4
5
6
7
8
var def = {
         urlOrData: false , //必须!请求数据的url和或者直接是数据,格式参考autocomplete的说明
         width: "90%" , //宽度
         addItem: false , //当从下拉选项中选择一我的员后触发的函数
         removeItem: false , //当从已选择的人员删除一我的时触发的函数
         clickItem: function () { }, //点击人员小方块时触发的时间
         completeOp: {} //autocomplete的参数,格式参考它自身的说明
     };

参数也是比较简单,添加和移除的两个函数比较重要,在demo中会讲到,autocomplete的参数由于太多,你们只有本身参考一下官方的说明, 默认无论也能够,由于我会给你们默认来一下.

1
2
3
4
5
$.extend(def, o);
//这才是默认的Complete的参数
  var co = $.extend({ scroll: false , formatItem: function (row, i, max) { return row[0] + "[" + row[1] + "]" ; } }, def.completeOp);
//定义小方块的模板,其中s.gif是个空图片,位置可根据实际状况进行调整
   var temp = "<div class=" bbit-usbox-item "><a href=" javascript:void(0); "><span>${text}</span><input value=" ${value} " type=" hidden "><img class=" bbit-usbox-del " alt=" 点击删除 " src=" ../Themes/Shared/images/s.gif "></a></div>" ;

formatItem函数是下拉中显示的格式 ,接着是生成HTML,注册事件,详细的步骤我已经注释到代码中了以下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
return this .each( function (e) {
             var me = $( this );
             var id = me.attr( "id" );
             //获取惟一的ID
             if (id == null || id == "" ) {
                 id = "usbox_" + new Date().getTime();
             }
             //input的容器
             var inc = $( "<div class='bbit-usbox-boxc'/>" );
             //生成一个input用于附加autocomplete控件
             var input = $( "<input type='text' id='" + id + "_inbox' class='bbit-usbox-box' />" ).appendTo(inc);
             //设置样式,并把input添加到对象中
             me.addClass( "bbit-usbox" ).width(def.width).append(inc);
             //给input注册autocomplete功能,并设置回调函数
             input.autocomplete(def.urlOrData, co).result( function (event, data, formatted) {
                 $( this ).val( "" ); //选择人员了则把输入框本身清空
                 additem( this , data); //生成小方块
             });
             //注册一个自定义的事件,事件名addboxitem
             me.bind( "addboxitem" , function (e,data) { additem(input,data); });
             function additem(inc, data) {
                 //小方块的模板替换成正确的值
                 var tp = $(temp.replace(/\$\{([\w]+)\}/g, function (s1, s2) {
                     if (s2 == "text" ) {
                         return data[0]; //返回的第一个值是displayname
                     }
                     else if (s2 == "value" ) {
                         return data.join( "|" ); //其余所有放到input[type=hidden]中
                     }
                     else {
                         return s1;
                     }
                 }));
                 //触发小放开的click事件,而且在内部查找删除按钮,注册点击事件,jQuery的链式哦
                 tp.click(def.clickItem).find( "img.bbit-usbox-del" ).click(removeitem);
                 //把小方块放到input以前!
                 $(inc).parent().before(tp);
                 if (def.addItem) { //若是additem存在则触发
                     def.addItem(data);
                 }
             }
             //移除的方法
             function removeitem() {
                 var p = $( this ).prev() //获取input[type=hidden],this指向delete img
                 var v = p.val();
                 var arr = v.split( "|" ); //拼成一个数组
                 if (def.removeItem) { //触发移除函数
                     def.removeItem(arr);
                 }
                 //小方块移除自己
                 $( this ).parent().parent().remove(); //
             }
             return me;
         });

最后是公开一个函数来方便外面调用additem,如我有一个弹出界面能够一次选择n我的回来,那么就能够调用这个函数了

1
2
3
$.fn.addboxitem = function (op) {
         $( this ).trigger( "addboxitem" , [op]); //想到我在以前注册的自定义事件了吗?
     };
至此咱们的控件其实已经分析完成了,可是为了让你们更好的理解这个控件,我把对应的服务器端代码也顺便写写由于Demo是Asp.NET MVC的,那么就以asp.net mvc 为例来说吧 先来看看Demo的调用代码,urlOrData是个Action,additem和removeitem分别处理将选中的人员添加到指定的隐藏域或从中删除,以便表单提交。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$(document).ready( function () {
             $( "#usbox" ).usbox({
                 width: 430,
                 urlOrData: "<%=Url.Action(" QueryComplete ")%>" ,
                 addItem: function (data) {
                     var t = $( "#hdtext" ).val();
                     var v = $( "#hdvalue" ).val();
                     var t1 = t != "" ? t.split( "," ) : [];
                     var v1 = v != "" ? v.split( "," ) : [];
                     t1.push(data[0]);
                     v1.push(data[2]);
                     $( "#hdtext" ).val(t1.join( "," ));
                     $( "#hdvalue" ).val(v1.join( "," ));
                 },
                 removeItem: function (data) {
                     var t = $( "#hdtext" ).val();
                     var v = $( "#hdvalue" ).val();
                     var t1 = t.split( "," );
                     var v1 = v.split( "," );
                     var index = -1;
                     for ( var i = v1.length - 1; i >= 0; i--) {
                         if (data[2] == v1[i]) {
                             index = i;
                             break ;
                         }
                     }
                     if (index > -1) {
                         t1.splice(index, 1);
                         v1.splice(index, 1);
                         $( "#hdtext" ).val(t1.join( "," ));
                         $( "#hdvalue" ).val(v1.join( "," ));
                     }
 
                 }
             });
             var tempdata = [ "假正经哥哥" , "xuanye" , "001" ];        
             $( "#usbox" ).addboxitem(tempdata);
         });

HTML代码

1
2
3
4
5
< div id="usbox" class="bbit-usbox">
</ div >
< input id="hdtext" type="text"/>
< input id="hdvalue" type="text"/>
输入框在实际项目中多是隐藏域,默认我加上了假正经哥哥
再来看看Action的代码,默认接受两个参数,一个是q,即input中的输入框,一个是限制条数(默认是10,可经过修改complete的参数来改变)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public ContentResult QueryComplete( string q, int limit)
         {
             string ret = "" ;
             if (q != "" && limit >0)
             {  
            //根据关键字搜索数据库或缓存,这个就比较简单不深刻了
                List<Person> list=_respository.QueryCompletePerson(q, limit);
                if (list != null )
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (Person person in list)
                    {
                //以|分割的数据格式,能够是多个,这里是三个。固然也能够吧ID做为特殊的
                        sb.AppendLine(person.FullName + "|" + person.PY+ "|" +person.ID);
                    }
                    ret = sb.ToString();
                }               
             }
             return Content(ret);
         }

本示例的地址是:http://jscs.cloudapp.net/ControlsSample/usbox

另外抱怨一下:部署到window azure 真的是有点麻烦哟。。搞了几回

最后 你的支持就是我继续写做的动力!

 

本文地址:http://www.cnblogs.com/xuanye/archive/2009/10/28/1591733.html

转载请保留!

出处:http://www.cnblogs.com/xuanye/archive/2009/10/28/xuanye_jquery_usbox_bog.html

相关文章
相关标签/搜索