jQuery自定义多选下拉框

 

  项目中需要自定义一个下拉框多选插件,业务问题还是自己实现比较好

 

  通过$.fn 向jQuery添加新的方法 

  

   下拉数据通过参数传递进去,通过调用该插件时接收,选择后的确定与取消事件采用事件传递方式

 

  代码如下:

 

 

1.效果图

2.代码

 1 <div id="demo" class="dropdown-container">
 2     <div class="dropdown-display">
 3       <span></span>
 4       <input type="text" class="iptdiplay" placeholder="请选择" readonly="readonly" />
 5     </div>
 6     <div class="dropdown-panel">
 7       <div class="dropdown-search">
 8         <span></span>
 9         <input type="text"  class="iptsearch" placeholder="关键字搜索" />
10       </div>
11       <ul class="dd-select">
12         <!--  area for dropdown items -->
13       </ul>
14       <div class="dropdown-opt">
15         <button class="dd-btn ok">确定</button>
16         <button class="dd-btn cancel">取消</button>
17       </div>
18     </div>
19   </div>

 

  1 .dropdown-container{
  2     display: block;
  3     width: 200px;
  4     height: 30px;
  5     padding: 0px;
  6     position: relative;
  7     margin: 0px auto;
  8 }
  9 
 10 .dropdown-display{
 11     display: block;
 12     height: 30px;
 13     position: absolute;
 14     top: 0;
 15     width:100%;
 16     margin: 0px;
 17     border:1px solid steelblue;
 18 }
 19 .dropdown-display span{
 20     background: url(../static/choose_down_icon_01.png) no-repeat left 8px;
 21     display: block;
 22     height: 25px;
 23     width: 10px;
 24     position: absolute;
 25     right: 5px;
 26     top: 3px;
 27 }
 28 .dropdown-display input[class='iptdiplay']{
 29     border: none;
 30     border-color: transparent;
 31     background: transparent;
 32     border-radius: 0px;
 33     box-shadow: none;
 34     height: 30px;
 35     width: 100%;
 36     margin: 0px;
 37     box-sizing: border-box;
 38     box-shadow: none;
 39     padding-left: 10px;
 40     padding-right: 18px;
 41     outline: none;
 42     cursor: pointer;
 43     text-overflow: ellipsis;
 44 }
 45 .dropdown-panel {
 46     position: absolute;
 47     top: 32px;
 48     width:100%;
 49     padding: 0px;
 50     display: none;
 51     border-left: 1px solid steelblue;
 52     border-bottom: 1px solid steelblue;
 53     border-right: 1px solid steelblue;
 54 }
 55 
 56 .dropdown-panel .dropdown-search{
 57     display: block;
 58     width: 100%;
 59     height: 30px;
 60 }
 61 .dropdown-search span{
 62     background: url(../static/chosen-sprite.png) no-repeat 100% -20px,linear-gradient(#eee 1%,#fff 15%);
 63     display: block;
 64     height: 25px;
 65     width: 20px;
 66     position: absolute;
 67     right: 0px;
 68     top: 3px;
 69 }
 70 .dropdown-search input[class='iptsearch']{
 71     border: none;
 72     border-color: transparent;
 73     background: transparent;
 74     border-radius: 0px;
 75     box-shadow: none;
 76     height: 30px;
 77     width: 100%;
 78     margin: 0px;
 79     box-sizing: border-box;
 80     box-shadow: none;
 81     padding-left: 10px;
 82     outline: none;
 83 }
 84 .dropdown-panel .dd-select{
 85     display: block;
 86     width:100%;
 87     position: relative;
 88     height: auto;
 89     margin: 0px;
 90     padding:0px !important;
 91     box-sizing: border-box;
 92     list-style-type: none;
 93     text-align: left;
 94     max-height: 300px;
 95     overflow-y: scroll;
 96     overflow-x: hidden;
 97 }
 98 .dd-item{
 99     display: block;
100     height: 30px;
101     line-height: 30px;
102     padding-left: 5px;
103     border-bottom: 1px solid steelblue;
104     font-size: 13px;
105     z-index: 8;
106     overflow: hidden;
107 }
108 .dd-item .dd-v{
109     width: 0px;
110     height: 0px;
111     display: none;
112 }
113 .dd-item .dd-k{
114     z-index: 8;
115     padding-left: 15px;
116 }
117 .dd-item:first-child{
118     border-top: 1px solid steelblue;
119 }
120 .dd-item:last-child{
121     border-bottom: none;
122 }
123 .dd-select .on{
124     background-color: steelblue\9;
125 }
126 .dd-item:hover::before,.dd-item:hover before{
127     content:'\2714';
128     position: absolute;
129     left: 0px;
130     color: #79a979
131     z-index: 9;
132     font-size: 16px;
133     padding-right: 3px;
134     padding-left: 2px;
135     background-color: #fff;
136 }
137 .dd-select .on::before,.dd-select .on before{
138     content:'\2714';
139     position: absolute;
140     left: 0px;
141     color: green;
142     z-index: 9;
143     font-size: 16px;
144     padding-right: 3px;
145     padding-left: 2px;
146     background-color: #fff;
147 }
148 .dd-item:hover{
149     cursor: pointer;
150     background-color: #ccc;
151 }
152 .dropdown-container .dropdown-opt{
153     width:100%;
154     text-align: center;
155     position: absolute;
156     left: -1px;
157     bottom: -30px;
158     padding: 0px;
159     border-left: 1px solid steelblue;
160     border-bottom: 1px solid steelblue;
161     border-right: 1px solid steelblue;
162     box-sizing: content-box;
163 }
164 .dropdown-container .dd-btn{
165     color: #333;
166     height: 28px !important;
167     display: inline-block;
168     background-color: #e6e6e6;
169     border-color: #adadad;
170     user-select: none;
171     background-image: none;
172     border: 1px solid transparent;
173     border-radius: 4px;
174     margin: 0px 15px;
175 }
176 .dropdown-container .dd-btn:hover{
177     color:#fff;
178     background-color: steelblue;
179 }
180 /* scrollbar */
181 .dropdown-container ::-webkit-scrollbar {  width: 5px;  height: 10px;  }  
182 .dropdown-container ::-webkit-scrollbar-track,  
183 .dropdown-container ::-webkit-scrollbar-thumb {  border-radius: 999px;  border: 5px solid transparent;  }  
184 .dropdown-container ::-webkit-scrollbar-track {  box-shadow: 1px 1px 5px rgba(0,0,0,.2) inset;  }  
185 .dropdown-container ::-webkit-scrollbar-thumb {  min-height: 20px;  background-clip: content-box;  box-shadow: 0 0 0 5px rgba(0,0,0,.2) inset;  }  
186 .dropdown-container ::-webkit-scrollbar-corner {  background: transparent;  }

3.Jquery插件

;(function ($,window,document,undefined) {
    var _pluginName="jqDropdown";

    var defaults = {
        items:[]
    };

    var parm=[];

    //es5 filter hack
    if (!Array.prototype.filter){
          Array.prototype.filter = function(fun){
            var len = this.length;
            if (typeof fun != "function") throw new TypeError(); 
             var res = new Array();
            var _arg = arguments[1];
            for (var i = 0; i < len; i++){
                  if (i in this){
                    var val = this[i];
                    if (fun.call(_arg, val, i, this)) res.push(val);
                  }
            } 
             return res;
          };
    }
    if(!Array.prototype.indexOf) {
        Array.prototype.indexOf = function (elem, startFrom) {
            var startFrom = startFrom || 0;
            if (startFrom > this.length) return -1;

            for (var i = 0; i < this.length; i++) {
                if (this[i] == elem && startFrom <= i) {
                    return i;
                } else if (this[i] == elem && startFrom > i) {
                    return -1;
                }
            }
            return -1;
        }
    }
    var init = function (o,opts,okFn,cancelFn) {
        var _panel=$(o);
        var _ul=_panel.find(".dd-select:eq(0)");

        function createDropItems(items,p){
            p=p||[];
            _ul.empty();
            var _curretVal=$(".iptdiplay").val();
            for(var i=0,len=items.length;i<len;i++){
                var _d=items[i];
                var _li='<li class="{{DC}}"> <span class="dd-v">{{DV}}</span><span class="dd-k">{{DK}}</span></li>';
                _ul.append(_li.replace(/{{DV}}/g, _d.val).replace(/{{DK}}/g,_d.name).replace(/{{DC}}/g,p.indexOf(_d.val.toString())>-1?'dd-item on':'dd-item'));
            }

            _panel.find('.dd-item').click(function(e){
                var $this=$(this);
                var _k_= $this.find('.dd-k:eq(0)').text()
                var _v_= $this.find('.dd-v:eq(0)').text();
                if($this.hasClass('on')){
                    parm=parm.filter(function(t){ return t!=_v_; });
                    $this.removeClass('on');
                }else{
                    parm.push(_v_);
                    $this.addClass('on');
                }

                var disArr=[];
                for(var i=0,len=items.length;i<len;i++){
                    var _d=items[i];
                    if(parm.indexOf(_d.val.toString())>-1) disArr.push(_d.name);
                }
                $(".iptdiplay").val(disArr.join('|'));
            });
        };

        //init to build dropdown items
        createDropItems(opts.items||[]);

        function toggleDrop(){

            $(".dropdown-panel").slideToggle();
        };

        
        //search
        $(".iptsearch").bind("input propertychange",function(e){
            if(!e) return;
            var _sk=e.currentTarget.value;
            var _items=opts.items||[];
            createDropItems(_items.filter(function(d){

                return d.name.indexOf(_sk)>-1; 
            }),parm);
        });

        //Toggle dropdown
        $(".dropdown-display").click(function(){

            toggleDrop();
        });

        //OK button event
        $(".dropdown-opt button.ok").click(function(){
            toggleDrop();
            okFn&&okFn.apply(this,[parm]);
        });

        //Cancel button event
        $(".dropdown-opt button.cancel").click(function(){

            toggleDrop();
            cancelFn&&cancelFn.call(this);
        });
    };

    $.fn[_pluginName] = function (options,okFn,cancelFn) {

        var options = $.extend(defaults, options);
        return this.each(function () {

            init(this,options,okFn,cancelFn);
        });
    }
})(jQuery,window,document);

 

4.页面调用示例

<script>

    var data=[
      { name:'http://58.100.3.12',val:1 },
      { name:'http://44.168.4.13',val:2 },
      { name:'http://192.168.2.1/sdfsf/234234/234/2/34/23',val:3 },
      { name:'http://220.199.5.14',val:4 },
      { name:'http://127.1.62.15',val:5 },
      { name:'http://127.1.62.15',val:6 },
      { name:'http://127.1.62.15',val:7 },
      { name:'http://127.1.62.15',val:8 },
      { name:'http://127.1.62.15',val:9 },
      { name:'http://127.1.62.15',val:10 },
      { name:'http://127.1.62.15',val:11 },
      { name:'http://127.1.62.15',val:12 },
      { name:'http://127.1.62.15',val:13 },
      { name:'http://127.1.62.15',val:14},
      { name:'http://127.1.62.15',val:15 },
      { name:'http://127.1.62.15',val:16 },
      { name:'http://127.1.62.15',val:17 },
      { name:'http://127.1.62.15',val:18 },
      { name:'http://127.1.62.15',val:19 },
      { name:'http://127.1.62.15',val:20 },
      { name:'http://127.1.62.15',val:21 },
      { name:'http://127.1.62.15',val:22 },
      { name:'http://127.1.62.15',val:23 },
      { name:'http://127.1.62.15',val:24 },
      { name:'http://127.1.62.15',val:25 },
      { name:'http://127.1.62.15',val:26 },
      { name:'http://127.1.62.15',val:27 },
      { name:'http://127.1.62.15',val:28 },
      { name:'http://127.1.62.15',val:29 }
    ];

    $("#demo").jqDropdown({ items:data },function(e){

      console.dir(e);
    },function(){

      console.log('canceled by user !');
    });

  </script>

 

5.输出

 6.不足

  页面样式在不支持css3浏览器中显示有问题 后期需要改进

     下拉数据为一次性渲染 如有需要 可设置滚动加载

     下拉框滚动条的美化未兼容所有浏览器

      搜索时检索数据直接源自页面数据 所有需要添加延迟处理 获取服务端数据

 

【原创】

posted @ 2016-12-19 17:00  迷惘却坚定  阅读(1278)  评论(0编辑  收藏  举报