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

來源:互聯網
上載者:User

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的樣子而已,來看下代碼

.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行代碼

; (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控制項的“模板”,關於為什麼要這麼寫,請參考這篇的說明

; (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 = $("<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個人回來,那麼就可以調用這個函數了

    $.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:"<%=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代碼

<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<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

轉載請保留!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.