UPDATE:修正了在FireFox下显示的问题,重新copy CSS即可

写完这个名字忽然觉得有点标题党的嫌疑,但是又不知道什么样的名字比较合适,那就暂且这样吧。

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

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

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

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

大家可以通过访问以下来获取它的使用方法,资料和demo还是比较详细,我这边就不重复写了。所以我们还是直接开始扩展的部分

第一我们还是先确定HTML

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

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

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

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

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

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
.bbit-usbox
{
    border: solid 1px #3C7FB1;       
    margin:20px;
    padding:2px;   
    display:block;
    background-color:#f3fefe;
}
.bbit-usbox .bbit-usbox-item
{
    width:auto;
    margin-left:4px;
    margin-top:2px;
    background-color:#e0e5ee;   
    border: solid 1px #ccd5e4;   
    float:left;  
    white-space : nowrap;
}
.bbit-usbox .bbit-usbox-item a
{
    color:#000;
    text-decoration:none;
    padding-left:2px;
}
.bbit-usbox .bbit-usbox-item a span
}
.bbit-usbox .bbit-usbox-del
{
    background:url("images/usbox/del.gif") no-repeat 50% 80%;
    width:10px;
    height:5px;
    cursor:pointer;
    border:none;
    vertical-align:middle;
    margin-left:2px;
}
.bbit-usbox-boxc
{
  margin-left:4px;
  clear:left;
}
.bbit-usbox-box
{
}
.bbit-usbox-boxc  input
{
    background-color:#f3fefe;
    width:100%;
    height:17px;
    display:block;
    border:none;   
}

本例中只有使用一个图片

第二 开始编写Javascript

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

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
55
56
57
58
59
60
61
62
63
64
65
66
67
; (function($) {
    if (!$.Autocompleter) {
        alert("请先引用jquery.autocomplete.js");
        return;
    }
    $.fn.usbox = function(o) {
        var def = {
            urlOrData: "ResponseAutoComplete.ashx",
            width: "90%", //宽度
            addItem: false,
            removeItem: false,
            clickItem: function() { },
            completeOp: {}
        };
        $.extend(def, o);
        var co = $.extend({ scroll: false, formatItem: function(row, i, max) { return row[0] + "[" + row[1] + "]"; } }, def.completeOp);
 
        var temp = "<div class='bbit-usbox-item'><a href='javascript:void(0);'><span>${text}</span><input type='hidden' value='${value}'/><img src='../Themes/Shared/images/s.gif' alt='点击删除' class='bbit-usbox-del'/></a></div>";
 
        return this.each(function(e) {
            var me = $(this);
            var id = me.attr("id");
            if (id == null || id == "") {
                id = "usbox_" + new Date().getTime();
            }
            var inc = $("<div class='bbit-usbox-boxc'/>");
            var input = $("<input type='text' id='" + id + "_inbox' class='bbit-usbox-box' />").appendTo(inc);
            me.addClass("bbit-usbox").width(def.width).append(inc);
            input.autocomplete(def.urlOrData, co).result(function(event, data, formatted) {
                $(this).val("");
                additem(this, data);
            });
            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];
                    }
                    else if (s2 == "value") {
                        return data.join("|");
                    }
                    else {
                        return s1;
                    }
                }));
                tp.click(def.clickItem).find("img.bbit-usbox-del").click(removeitem);
                $(inc).parent().before(tp);
                if (def.addItem) {
                    def.addItem(data);
                }
            }
            function removeitem() {
                var p = $(this).prev()
                var v = p.val();
                var arr = v.split("|");
                if (def.removeItem) {
                    def.removeItem(arr);
                }
                $(this).parent().parent().remove();
            }
            return me;
        });
    };
    $.fn.addboxitem = function(op) {
        $(this).trigger("addboxitem", [op]);
    };
})(jQuery)

接着我们来一步一步来分析我的实现,开始还是编写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

打造基于jQuery的智能选择输入框的更多相关文章

  1. 打造基于jQuery的日期选择控件

    终于把jQuery拼写正确了哈,哈哈javascript也是区分大小写的,所以确实不能写错,今天我来和大家分享的是日期选择控件的实现,功能也许不够强大,但是能够满足需求. 我之前也写过(正确的说是改过 ...

  2. 基于jquery的城市选择插件

    城市选择插件的难度不是很大,主要是对dom节点的操作.而我写的这个插件相对功能比较简答,没有加入省市联动. 上代码好了,参照代码的注释应该比较好理解. /* *基于jquery的城市选择插件 *aut ...

  3. 基于jquery的ui选择之路

    选定: 主框架:jqueryUi tree:ztree grid:jqGrid layout:jquery.layout 原由: 还有其他demo,ajax实现等参看连接: 正在做的一个项目选择jqu ...

  4. 福利到~分享一个基于jquery的智能提示控件intellSeach.js

    一.需求 我们经常会遇到[站内搜索]的需求,为了提高用户体验,我们希望能做到像百度那样的即时智能提示.例如:某公司人事管理系统,想搜索李XX,只要输入“李”,系统自然会提示一些姓李的员工,这样方便用户 ...

  5. 一个基于jquery的智能提示控件intellSeach.js

    一.需求 我们经常会遇到[站内搜索]的需求,为了提高用户体验,我们希望能做到像百度那样的即时智能提示.例如:某公司人事管理系统,想搜索李XX,只要输入“李”,系统自然会提示一些姓李的员工,这样方便用户 ...

  6. jquery的智能提示控件

    福利到~分享一个基于jquery的智能提示控件intellSeach.js   一.需求 我们经常会遇到[站内搜索]的需求,为了提高用户体验,我们希望能做到像百度那样的即时智能提示.例如:某公司人事管 ...

  7. 基于jQuery的input输入框下拉提示层(自动邮箱后缀名)

    基于jQuery的input输入框下拉提示层,方便用户输入邮箱时的提示信息,需要的朋友可以参考下     效果图   // JavaScript Document (function($){ $.fn ...

  8. 基于jQuery打造的选项卡向上弹出jquery焦点图切换特效

    基于jQuery打造的选项卡向上弹出jquery焦点图切换特效 鼠标经过标题栏,会出现层特效向上滑动,并且在同时进行幻灯片切换,效果十分不错. 有兴趣的童鞋可以下载看看,在IE6方面兼容性也不错,只有 ...

  9. 基于jQuery美化联动下拉选择框

    今天给大家介绍一款基于jQuery美化联动下拉选择框.这款下下拉选择框js里自带了全国所有城市的数数库.下拉选择框适用浏览器:IE8.360.FireFox.Chrome.Safari.Opera.傲 ...

随机推荐

  1. MySQL从删库到跑路(二)——MySQL字符集与乱码解析

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.字符集与编码 1.字符集简介 字符(Character)是各种文字和符号的总称,包括各国家文字.标点符号.图形符 ...

  2. GreenOpenPaint的实现(二)打开显示图片

    1.DOC中添加,核心图片文件保存在这里.之所以不用Mat,是因为CVVImage有更好的输入输出函数. 我这里直接使用了public public: CvvImage m_image; 2.重载打开 ...

  3. 20145204 《Java程序设计》第7周学习总结

    20145204 <Java程序设计>第7周学习总结 教材学习内容总结 时间 GMT.UT.TAI 格林威治标准时间(GMT)的正午是太阳抵达天空最高点之时,因为地球公转轨道为椭圆且速度不 ...

  4. personal evolution

    自我清醒 认知自我的行为和心理 你确定你自己是出于理智而发出某种行为? 首先需要确定哪些是人的天性 认知失调理论 从众效应 晕轮效应 霍桑效应 马太效应 期望效应 刻板效应 破窗效应 安排思维 安排闲 ...

  5. SqlBulkCopy 批量导入数据 转换表字段类型

    在使用SqlBulkCopy导入数据时,要有一个跟数据库里面同样的DataTable 要赋值表名 要求每个列跟数据库中列同名,并且列的类型要赋值跟数据库中列的类型对应的NET类型 要求数据库中为Nul ...

  6. HDU 3820 Golden Eggs

    http://acm.hdu.edu.cn/showproblem.php?pid=3820 题意:n*m的格子,每个格子放金蛋或银蛋,每个格子的金蛋和银蛋都有一个对应的点权,如果有两个金蛋相连,则需 ...

  7. php 关联数组遍历

    <?php $age=array("); foreach($age as $x=>$x_value) { echo "Key=" . $x . ", ...

  8. ResourceNotFound: rosbridge_server

    Checking log directory for disk usage. This may take awhile. Press Ctrl-C to interrupt Done checking ...

  9. windows下的IO模型之完成端口

    本文整理于:http://blog.csdn.net/piggyxp/article/details/6922277 一. 完成端口的优点 完成端口会充分利用Windows内核来进行I/O的调度,是用 ...

  10. 运用模型绑定和web窗体显示和检索数据(Retrieving and displaying data with model binding and web forms)

    原文 http://www.asp.net/web-forms/overview/presenting-and-managing-data/model-binding/retrieving-data ...