打造基於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的說明
         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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM