基于jQuery打造智能的人員選擇輸入框

作者: 假正經哥哥  來源: 博客園  發布時間: 2009-10-29 17:40  閱讀: 11706 次  推薦: 3   原文鏈接   [收藏]  

寫完這個名字忽然覺得有點標題黨的嫌疑,但是又不知道什么樣的名字比較合適,那就暫且這樣吧。

今天要講的東西比較簡單,其中會用到另外的一個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的樣子而已,來看下代碼

.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;    
}

 

 

本例中只有使用一個圖片 del

第二 開始編寫Javascript

還是老規矩,先來個完整代碼,非常簡單只有不到70行代碼

; (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 = "${text}";

        return this.each(function(e) {
            var me = $(this);
            var id = me.attr("id");
            if (id == null || id == "") {
                id = "usbox_" + new Date().getTime();
            }
            var inc = $("");
            var input = $("").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控件的“模板”,關于為什么要這么寫,請參考這篇的說明

 

; (function($) {
    if (!$.Autocompleter) { 
        alert("請先引用jquery.autocomplete.js");
        return;
    }
   $.fn.usbox = function(o) {
   }
})(jQuery)

這次加了一個判斷,因為我們這個控件是依賴于autocomplete的,如果你看了前兩篇,那么就一定知道接著就是編寫默認參數

    var def = {
            urlOrData:false,//必須!請求數據的url和或者直接是數據,格式參考autocomplete的說明
            width: "90%", //寬度
            addItem: false,//當從下拉選項中選擇一個人員后觸發的函數
            removeItem: false,//當從已選擇的人員刪除一個人時觸發的函數
            clickItem: function() { },//點擊人員小方塊時觸發的時間
            completeOp: {}//autocomplete的參數,格式參考它自身的說明
        };

參數也是比較簡單,添加和移除的兩個函數比較重要,在demo中會講到,autocomplete的參數因為太多,大家只有自己參考一下官方的說明, 默認不管也可以,因為我會給大家默認來一下.

$.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 = "${text}";

formatItem函數是下拉中顯示的格式 ,接著是生成HTML,注冊事件,詳細的步驟我已經注釋到代碼中了如下所示

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 = $("");
            //生成一個input用于附加autocomplete控件
            var input = $("").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個人回來,那么就可以調用這個函數了

$.fn.addboxitem = function(op) {
        $(this).trigger("addboxitem", [op]);//想到我在之前注冊的自定義事件了嗎?
    };

至此我們的控件其實已經分析完成了,但是為了讓大家更好的理解這個控件,我把對應的服務器端代碼也順便寫寫因為Demo是Asp.NET MVC的,那么就以asp.net mvc 為例來講吧 先來看看Demo的調用代碼,urlOrData是個Action,additem和removeitem分別處理將選中的人員添加到指定的隱藏域或從中刪除,以便表單提交。

$(document).ready(function() {
            $("#usbox").usbox({
                width: 430,
                urlOrData:"",
                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代碼

<div id="usbox" class="bbit-usbox">  </div> 
<input id="hdtext" type="text"/> 
<input id="hdvalue" type="text"/> 
輸入框在實際項目中可能是隱藏域,默認我加上了假正經哥哥

再來看看Action的代碼,默認接受兩個參數,一個是q,即input中的輸入框,一個是限制條數(默認是10,可通過修改complete的參數來改變)

public ContentResult QueryComplete(string q, int limit)
        {
            string ret = "";
            if (q != "" && limit >0)
            {    
           //根據關鍵字搜索數據庫或緩存,這個就比較簡單不深入了
               List 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);
        }
3
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()