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. pug 在线文档

    https://pugjs.org/zh-cn/api/getting-started.html

  2. [one day one question] express 不缓存如何实现

    问题描述: express 默认缓存,这怎么破? 解决方案: apiRoutes.use(function (req, res, next) { res.setHeader('Cache-Contro ...

  3. Centos下给PHP一键升级高版本7.2.0

    我是在Centos下测试的,目前php版本是7.0.0,我要升级到php7.2.0,下面开始. 执行命令 # wget http://soft.vpser.net/lnmp/upgrade_php.s ...

  4. Python3.x:bs4解析html基础用法

    Python3.x:bs4解析html基础用法 代码: import urllib.request from bs4 import BeautifulSoup import re url = r'ht ...

  5. linux history记录格式修改

    #保存一万条命令记录 sed -i 's/^HISTSIZE=1000/HISTSIZE=10000/g' /etc/profile #在/etc/profile的文件尾部添加如下行数配置信息 ### ...

  6. 20145311 《Java程序设计》第九周学习总结

    20145311 <Java程序设计>第九周学习总结 教材学习内容总结 第十六章 整合数据库 16.1JDBC 16.1.1JDBC简介 JDBC(Java DataBase Connec ...

  7. 计算机基础教程11 - 互联网&内联网

    在本章中,我们将看到什么是Internet和Intranet,以及讨论两者之间的异同. 互联网 它是互联计算机网络的全球/全球系统.它使用标准的Internet协议(TCP / IP).Interne ...

  8. CCNA学习指南 -开放最短路径优先OSPF(单区域)

    在上个世纪九十年代撰写的<TCP/IP协议详解 卷一:协议>的动态选路中,内容大部分还是介绍 RIP路由选择信息协议,在互联网络如此发达的今天,RIP因为它的局限性逐步被OSPF取代. 在 ...

  9. 为什么要使用MQ消息中间件?它解决了什么问题?

    1.应用场景 1.1 异步处理 场景说明:用户注册后,需要发注册邮件和注册短信,传统的做法有两种1.串行的方式;2.并行的方式 (1)串行方式:将注册信息写入数据库后,发送注册邮件,再发送注册短信,以 ...

  10. UVA-10129 Play on Words (判断欧拉道路的存在性)

    题目大意:给出一系列单词,当某个单词的首字母和前一个单词的尾字母相同,则这两个单词能链接起来.给出一系列单词,问是否能够连起来. 题目分析:以单词的首尾字母为点,单词为边建立有向图,便是判断图中是否存 ...