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


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

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

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

     image

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

    image

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

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

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

    第一我们还是先确定HTML

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

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

    容器我们用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的说明
             "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({
                     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

  • 相关阅读:
    Corn Fields
    状压DP
    全排列函数
    搜索
    前缀和与差分
    最小花费
    【Lintcode】062.Search in Rotated Sorted Array
    【LeetCode】039. Combination Sum
    【LeetCode】040. Combination Sum II
    【LeetCode】047. Permutations II
  • 原文地址:https://www.cnblogs.com/mq0036/p/8482578.html
Copyright © 2020-2023  润新知