基于jquery的可查询多级select控件(可记录历史选择)

一、功能和使用

公司有功能需求,还要一条代码引入的控件,网上找完全符合的控件比较难,寻找所花的时间还不如自己写一个,所以找个空闲时间自己写了一个
 
控件功能:1、可手动输入查询,也可点击下拉框查询,
2、输入时实时定位到下拉框,enter补全
3、可多级查询(目前是写到二级)
4、localStorage存储历史记录
 
控件使用:引入相应的js和css文件,需要控件的html中加一个div
<div id="multiple_select" class="multiple-select-container"></div> 

js里引入控件

$("#multiple_select").multiSelect({
         type:'2',//可选择几级数据
         data:data.list,      
      noneSelectedText: '请选择',
         field:['provence','city','name']  //option字段,【一级字段,二级字段,显示字段】
  }); 

二、代码

HTML
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>树形控件</title>
    <link rel="stylesheet" type="text/css" href="./multiSelect.css" />    
  </head>
  <body style="padding:100px;">  
      <div id="multiple_select" class="multiple-select-container"></div>     
  <script src="plugins/jquery-1.10.2.js"></script>
  <script src="./multiSelect.js"></script>
  <script>
    $(function(){
      //测试用的数据
      var data = {
      list:[{
              provence:"湖北",
              city:[{name:"武汉",code:1}, {name:"仙桃",code:2},{name:"天门",code:3}]
          },          
            {
              provence:"河北",
              city:[{name:"石家庄",code:1}, {name:"邯郸",code:2},{name:"唐山",code:3}]
          },{
              provence:"湖南",
              city:[{name:"郴州",code:1}, {name:"岳阳",code:2},{name:"长沙",code:3}]
          }]          
      }
      //控件引用
      $("#multiple_select").multiSelect({
         type:'2',//可选择几级数据
         data:data.list,
         field:['provence','city','name'] , //option字段,第一个是1级展示数据的字段,第二个是二级数据字段,第三个是显示字段
   record: true,  //是否需要历史记录功能,只展示最近使用的前三条数据
        noneSelectedText : '', //未选择时展示数据
      });
    });
  </script> 
  </body>
</html>

 

CSS

* {
    padding: 0;
    margin: 0;
}

ul li {
    list-style: none;
}


/*fontclass*/

@font-face {
    font-family: "iconfont";
    src: url('iconfont.eot?t=1537237853618');
    /* IE9*/
    src: url('iconfont.eot?t=1537237853618#iefix') format('embedded-opentype'), /* IE6-IE8 */
    url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAVYAAsAAAAACCQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFY8hUioY21hcAAAAYAAAABoAAABquZlt9xnbHlmAAAB6AAAAV8AAAG8iReSsmhlYWQAAANIAAAALAAAADYSq0zoaGhlYQAAA3QAAAAcAAAAJAfeA4ZobXR4AAADkAAAAA4AAAAUFAAAAGxvY2EAAAOgAAAADAAAAAwA2AFKbWF4cAAAA6wAAAAfAAAAIAESADtuYW1lAAADzAAAAUUAAAJtPlT+fXBvc3QAAAUUAAAAQgAAAFf+vnWeeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2BkYWCcwMDKwMHUyXSGgYGhH0IzvmYwYuRgYGBiYGVmwAoC0lxTGBye8T/bxtzwv4EhhrmBoQEozAiSAwDr4gyoeJztkcENgCAMRV8FjTEmhj0cwKPDeHI/GalrYFscw08e+f1pORRgBJKxGxnkRnBdlkrkiSXyzGH1bGcA3bRobe1zj7uQRMccr4nNWq9M/FrjPr8q+9464UvHN65Px39Fa4fhBcRnF9R4nE2QP0/CQBiH732vtrRXwcT+wRBabWKLS4lt02646IgTwbBRZhkYlX4BExNC4uTiqFE+BHwL+DBePFoTveF+l8tzz+/yEiRi0RHuCCMBIVAHxQG7B1kIx5Yhe11QZM9PriDwkzRyIUsjy2gASssNpZvlci1Ja4dZbX1eMMfUikIzHVbM9bbFCtxK64oQO4+ZuJvPBcuK4t9ZlJZ/eMUJMQjJVLCi1A9EYeDLCsgORNknDGCku01o8JfaAbITxhcqNF19BXf8i9muDvc1CpKk8oXA9D/neO9U0fdkywbbsq00gzQET6FDvuLvpVO8LZ0wK5044B8w3EtFWSmFWSmlpXNGL8kROSMhIedeiEkPIweNOlKvjoaDUQ+TEEHuQjUwMUR4u3nMoyh/fKriOpv0O53+ZFoFPByynWa22FYznuOKisf7iHHcuc1/sWnev/g+BbZlLVPbsZbxAzYBVaMAeJxjYGRgYADikyacs+P5bb4ycLMwgMD1Yy2xyDQLA7MhkOJgYALxAArgCJB4nGNgZGBgbvjfwBDDwgACQJKRARWwAgBHCwJueJxjYWBgYEHDAAEEABUAAAAAAAAAQgBsAJYA3nicY2BkYGBgZdBnYGYAASYg5gJCBob/YD4DAA2tAU4AeJxlj01OwzAQhV/6B6QSqqhgh+QFYgEo/RGrblhUavdddN+mTpsqiSPHrdQDcB6OwAk4AtyAO/BIJ5s2lsffvHljTwDc4Acejt8t95E9XDI7cg0XuBeuU38QbpBfhJto41W4Rf1N2MczpsJtdGF5g9e4YvaEd2EPHXwI13CNT+E69S/hBvlbuIk7/Aq30PHqwj7mXle4jUcv9sdWL5xeqeVBxaHJIpM5v4KZXu+Sha3S6pxrW8QmU4OgX0lTnWlb3VPs10PnIhVZk6oJqzpJjMqt2erQBRvn8lGvF4kehCblWGP+tsYCjnEFhSUOjDFCGGSIyujoO1Vm9K+xQ8Jee1Y9zed0WxTU/3OFAQL0z1xTurLSeTpPgT1fG1J1dCtuy56UNJFezUkSskJe1rZUQuoBNmVXjhF6XNGJPyhnSP8ACVpuyAAAAHicY2BigAAuBuyAlZGJkZmRhZGVkY2BJzknvzhVNzmzKDknlSOxqCi/XLe0gAvCSMkvz2MrTk0sSs5gYAAATLsOxwAA') format('woff'), url('iconfont.ttf?t=1537237853618') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
    url('iconfont.svg?t=1537237853618#iconfont') format('svg');
    /* iOS 4.1- */
}

.iconfont {
    font-family: "iconfont" !important;
    font-size: 16px;
    font-style: normal;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.icon-close-circle:before {
    content: "\e611";
}

.icon-arrow-up:before {
    content: "\e6b6";
}

.icon-arrow-down:before {
    content: "\e6b5";
}

.icon-search:before {
    content: "\e60f";
}


/*fontclass end*/

.multiple-select-container {
    width: 166px;
    height: 34px;
    line-height: 34px;
    position: relative;
    display: inline-block;
    vertical-align: middle;
}

.multiple-select-container .select-inputbox {
    width: 100%;
    height: 40px;
    line-height: 40px;
    padding: 0 9px;
    position: relative;
    box-sizing: border-box;
}

.multiple-select-container .select-input,
.multiple-select-container .select-button {
    width: 100%;
    height: 100%;
    outline: none;
    box-sizing: border-box;
    background: #FFF;
}

.multiple-select-container .select-input {
    padding: 5px 22px;
    border-radius: 2px;
    border: 1px solid #CFCFCF;
    height: 28px;
}

.multiple-select-container .select-button {
    padding: 5px 25px 5px 12px;
    border: 1px solid #CFCFCF;
    border-radius: 4px;
    text-align: left;
    display: flex;
    justify-content: space-between;
}

.multiple-select-container .select-button span {
    display: inline-block;
    height: 100%;
    line-height: 22px;
}

.multiple-select-container .selected-data {
    width: 80%;
    color: #333;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.multiple-select-container .input-isfold {
    float: right;
    cursor: pointer;
    margin-right: -16px;
    font-size: 12px;
}

.multiple-select-container .input-search,
.multiple-select-container .input-close {
    position: absolute;
    cursor: pointer;
    top: 50%;
    transform: translateY(-50%);
    display: inline-block;
    height: 16px;
    line-height: 16px;
    font-size: 18px;
}

.multiple-select-container .input-close {
    left: calc(95% - 22px);
    width: 12px;
    color: #7B7B7B;
    display: none;
}

.multiple-select-container .input-search {
    color: #ADADAD;
    left: 12px;
    width: 16px;
}

.multiple-select-container .select-options-box {
    width: 100%;
    display: none;
    position: absolute;
    border: 1px solid #c2cad8;
    z-index: 999999;
    background: #fff;
    height: 300px;
    overflow-y: auto;
}

.multiple-select-container .options-container {
    width: 100%;
    height: auto;
}

.multiple-select-container .options-record,
.multiple-select-container .optionslist {
    font-size: 14px;
    width: 100%;
    box-sizing: border-box;
    padding: 0 9px;
    text-align: left;
}

.multiple-select-container .options-record {
    color: #999;
    height: 34px;
    line-height: 34px;
}

.multiple-select-container .optionslist {
    cursor: pointer;
    height: 26px;
    line-height: 26px;
}

.multiple-select-container .optionslist:hover {
    background: #DEEDFF;
}

.multiple-select-container .options-one {
    font-size: 16px;
}

.multiple-select-container .options-two {
    width: 100%;
    font-size: 14px;
}

.multiple-select-container .options-two li {
    padding-left: 15px;
}

.multiple-select-container .options-isfold {
    float: right;
    display: inline-block;
    width: 16px;
}

.multiple-select-container .active-border {
    border: 1px solid #009BE1;
}

.multiple-select-container .background-color {
    background: #ECECEC!important;
}

.multiple-select-container .border-bottom {
    border-bottom: 2px solid #D4D4D4;
}

::-webkit-scrollbar {
    width: 5px;
    height: 5px;
}

::-webkit-scrollbar-thumb {
    background: #DCDCDC;
    border-radius: 8px;
}

  JS 

 ;
 (function($, window, document) {

     var pluginName = 'multiSelect',
         defaults = {
             type: '1', //select层级onetwo
             data: [], //数据
             field: [], //数据字段名 
             record: false, //是否记录最近使用的三条数据
             chooselast: true, //是否在初始化后自动选择最近使用的选项,record必须为true
             noneSelectedText: '', //未选择时显示文字
             isfoldFirst: false, //是否默认展开二级目录
             disabled: '', //是否禁用
             hasinput: true, //是否显示搜索框
             id: '', //id字段名
             allselect: '', //全选或者不选择
             queryFun: function() {}, //搜索方法

         };

     function MultiSelect(element, options) {
         this.element = element;
         this.settings = $.extend({}, defaults, options);
         this.init();
     }

     MultiSelect.prototype = {

         //初始化弹出框
         init: function() {
             var that = this,
                 element = this.element;

             that.create(element);
             that.triggerlist(element);
         },

         //创建select框
         create: function(element) {
             var that = this,
                 $this = $(element),
                 noneSelectedText = that.settings.noneSelectedText,
                 selectElement = '<button name="selectinput" class="select-button">' +
                 '<span id="selected_data" class="selected-data">' + noneSelectedText + '</span><span class="input-isfold iconfont icon-arrow-down"></span></button>' +
                 '<div class="select-options-box" id="select_options_box"></div>';
             $this.append(selectElement);
             var $options_box = $this.find('#select_options_box');
             $this.on({
                 'hideoptions': function(e) {
                     $options_box.fadeOut();
                     $this.find('.input-isfold').toggleClass('icon-arrow-down icon-arrow-up');
                 },
                 'showoptions': function(e) {
                     $options_box.fadeIn();
                     $this.find('.input-isfold').toggleClass('icon-arrow-down icon-arrow-up');
                 }

             });
             that.initOption(element);
         },
         //初始化列表
         initOption: function(element) {
             var that = this,
                 $this = $(element),
                 $options_box = $this.find('#select_options_box');
             var $options = that.parseOptions();
             $options_box.html($options);
         },
         //解析并处理options数据
         parseOptions: function() {
             var that = this,
                 type = that.settings.type,
                 field = that.settings.field,
                 one = field[0],
                 two = field[1],
                 data = that.settings.data,
                 allselect = that.settings.allselect,
                 hasinput = that.settings.hasinput,
                 disabled = that.settings.disabled,
                 twolist = '',
                 optionsTwo = [],
                 record = that.settings.record,
                 noneSelectedText = that.settings.noneSelectedText,
                 options = '';
             var recordColumn = JSON.parse(window.localStorage.getItem("recordInfo")) ? JSON.parse(window.localStorage.getItem("recordInfo")) : [];
             console.log("recordColumn" + recordColumn);
             options += '<div class="options-container">';
             if (record && recordColumn.length > 0) {
                 options += '<div class="options-record"><span class="options-data">最近使用</span>' +
                     '</div>';
                 for (var i = 0; i < recordColumn.length; i++) {
                     if (recordColumn[i] != undefined && JSON.stringify(data).indexOf(JSON.stringify(recordColumn[i].id)) >= 0) {
                         options += '<div class="optionslist" disabled="' + disabled + '" id="' + recordColumn[i].id + '" data-index=' + recordColumn[i].dataIndex + '">' +
                             '<span class="options-data">' + recordColumn[i][one] + '</span></div>';
                     } else {
                         recordColumn.splice(i, 1);
                         window.localStorage.setItem("recordInfo", JSON.stringify(recordColumn));
                     }
                 }
             }
             if (noneSelectedText) {
                 options += '<div class="options-record optionslist" id="none_selected_all"><span class="options-data">' + noneSelectedText + '</span></div>';
             }
             if (hasinput) {
                 options += '<div class="select-inputbox"><input type="text" name="selectinput" id="select_input" class="select-input" placeholder="" />' +
                     '<i class="input-search iconfont icon-search"></i>' +
                     '<i class="input-close iconfont icon-close-circle"></i></div>';
             }
             switch (type) {
                 case '1':
                     for (var i in data) {
                         options += '<div class="optionslist" disabled="' + disabled + '" id="' + data[i].id + '" data-index="' + i + '"><span class="options-data">' + data[i][one] + '</span></div>';
                     }
                     break;
                 case '2':
                     for (var i in data) {
                         twolist = '', optionsTwo = [];
                         var optionsTwo = data[i][two];

                         for (var j in optionsTwo) {
                             twolist += '<li class="options-container optionslist" disabled="' + disabled + '" id="' + data[i].id + '" data-index="' + i + '" data-twoindex="' + j + '">' +
                                 '-- ' + '<span class="options-data">' + optionsTwo[j][field[2]] + '</span></li>';
                         }
                         options += '<div class="options-one optionslist" disabled="' + disabled + '" id="' + data[i].id + '" data-index="' + i + '">' +
                             '<span class="options-data">' + data[i][one] + '</span><span class="iconfont icon-arrow-up options-isfold"></span>' +
                             '</div>' +
                             '<ul class="options-two">' + twolist + '</ul>';
                     }
                     break;
             }
             options += '</div>';
             return options;
         },

         //系列事件
         triggerlist: function(element, event) {
             var that = this,
                 $this = $(element),
                 data = that.settings.data,
                 field = that.settings.field,
                 one = field[0],
                 two = field[1],
                 isfoldFirst = that.settings.isfoldFirst,
                 noneSelectedText = that.settings.noneSelectedText,
                 $options_box = $this.find('#select_options_box'),
                 $isfold = $this.find('.options-isfold'),
                 record = that.settings.record,
                 chooselast = that.settings.chooselast,
                 disabled = that.settings.disabled,
                 $input = $this.find('#select_input'),
                 $selected = $this.find('#selected_data'),
                 $button = $this.find('.select-button');
             var recordColumn = JSON.parse(window.localStorage.getItem("recordInfo")) ? JSON.parse(window.localStorage.getItem("recordInfo")) : [];
             $input.on({
                 'input propertychange': function() {
                     that.selectFun(false, false, element);
                 },
                 'click': function() {
                     $options_box.show();
                     return false;
                 }
             });
             $this.find('.input-search').on('click', function(event) {
                 $this.trigger('showoptions', e);
                 that.selectFun(false, false, element);
                 return false;
             });
             $this.find('.input-close').on('click', function(event) {
                 $options_box.show();
                 $input.val('');
                 $(this).hide();
                 return false;
             });
             $button.on('click', function(event) {
                 $(this).addClass('active-border');
                 $options_box.toggle();
                 that.selectFun(false, true, element);
                 $this.find('.input-isfold').toggleClass('icon-arrow-down icon-arrow-up');
                 event.stopPropagation();
             })
             $isfold.on('click', function(event) {
                     //  that.selectFun(false, true, element);
                     $(this).parent().next().toggle();
                     $(this).toggleClass('icon-arrow-down icon-arrow-up');
                     $options_box.show();
                     //  $this.trigger('showoptions');
                     event.stopPropagation();
                 })
                 //选择事件
             $this.find('.optionslist').on({
                 'click': function(event) {
                     if (disabled) return;
                     $button.removeClass('active-border');
                     $(this).addClass('background-color');
                     $this.find('.optionslist').removeAttr("selected");
                     $(this).attr("selected", "selected");
                     $selected.html($(this).find('.options-data').html());
                     if ($.isFunction(that.settings.queryFun)) {
                         that.settings.queryFun();
                     }
                     if ($(this).attr("id") === "none_selected_all") {
                         $button.data("data", null)
                         $selected.html(noneSelectedText);
                     } else {
                         var recordIndex = parseInt($(this).attr("data-index")),
                             twoIndex = parseInt($(this).attr("data-twoindex")),
                             a = {},
                             b = { dataIndex: recordIndex };
                         if ($(this).attr("data-twoindex")) {
                             a = data[recordIndex][two][twoIndex];
                         } else {
                             a = data[recordIndex];
                         }
                         recordCol = $.extend(a, b);
                         $button.attr("data-index", recordIndex);
                         $button.data("data", a)
                         if (record) {
                             //  console.log("recordCol:" + recordCol + " recordColumn:" + JSON.stringify(recordColumn));
                             var len = recordColumn.length,
                                 existIndex = -1;
                             //  if (JSON.stringify(recordColumn).indexOf(JSON.stringify(recordCol)) > -1) {
                             for (var i = 0; i < len; i++) {
                                 if (recordColumn[i].dataIndex == recordIndex) {
                                     existIndex = i;
                                 }
                             };
                             if (existIndex > -1) {
                                 recordColumn.splice(existIndex, 1);
                             }
                             //  };
                             recordColumn.unshift(recordCol);
                             len = recordColumn.length;
                             if (len > 3) {
                                 recordColumn.splice(3, len - 3);
                             }
                             window.localStorage.setItem("recordInfo", JSON.stringify(recordColumn));
                         }
                     }
                     // $button.attr("data", a)

                     $this.trigger('hideoptions');
                     event.stopPropagation();
                 },
                 'mouseover': function() {
                     $(this).css({ 'background': '#DEEDFF' });
                 },
                 'mouseout': function() {
                     $(this).css({ 'background': '#fff' });
                 }
             });

             $(document).keyup(function(event) {
                 if (event.keyCode === 13&&$input.is(':focus')) {
                     that.selectFun(true, false, element);
                     if ($.isFunction(that.settings.queryFun)) {
                         that.settings.queryFun();
                     }
                 }
                 event.stopPropagation();
             });
             /* $(document).on('click', function(event) {
                 $options_box.hide();
             }); */
             $(document).on('click', function(event) {
                 var _tar = $button.children();
                 if (!_tar.is(event.target) && _tar.has(event.target).length === 0) { // Mark 1
                     $options_box.fadeOut();
                     $button.removeClass('active-border');
                 }
             });
             if (chooselast && record && recordColumn.length > 0) {
                 $this.find('.optionslist').first().trigger("click");
             }
             if (!isfoldFirst) {
                 $isfold.trigger("click");
             }
         },

         // input与select同步
         selectFun: function(enter, button, element) { //enter为true代表是键盘enter键,button为true代表是select,为false代表是input搜索框
             var that = this,
                 $this = $(element),
                 data = that.settings.data,
                 $options_box = $this.find('#select_options_box'),
                 $input = $this.find('#select_input'),
                 options = $this.find('.optionslist'),
                 $selected = $this.find('#selected_data'),
                 optionTop = 0,
                 selectHTML = '';
             var optiondata = button ? $selected.html() : $input.val();
             if ($input.val()) {
                 $this.find('.input-close').show();
             } else {
                 $this.find('.input-close').hide();
             }
             $.each(options, function(i, item) {
                 selectHTML = $(item).find('.options-data').html();
                 // console.log(selected); 
                 if (selectHTML.indexOf(optiondata) >= 0) {
                     // $(item).trigger('hover');
                     options.removeClass('background-color');
                     $(item).addClass('background-color');
                     /*if ($(item).hasClass('options-one')) {
                       optionTop = $(item).position().top;                                
                     }else{
                       optionTop = $(item).parent().position().top;
                     }*/
                     optionTop = $(item).position().top;
                     // console.log(optionTop);
                     $options_box.scrollTop(optionTop);
                     if (enter) {
                         $(item).trigger('click');
                     }
                 }
             });

             if (optiondata === '') {
                 options.removeClass('background-color');
                 $options_box.scrollTop(0);
             }
         }

     };

     $.fn[pluginName] = function(options) {
         this.each(function() {
             if (!$.data(this, "plugin_" + pluginName)) {
                 $.data(this, "plugin_" + pluginName, new MultiSelect(this, options));
             }
         });
         return this;
     };

     //外部获取选中数据
     $.fn.extend({
         optionSelected: function() {
             if ($(this).find("button").data("data")) {
                 return $(this).find("button").data("data");
             } else {
                 return "";
             }
         },
         setOption: function(id) {
             if (id && id != "" && id.length > 0) {
                 $(this).find("#" + id).trigger('click');
             }
         },
         setDisabled: function() {
             $(this).find("button").css("background-color", "#ccc");
             $(this).css("pointer-events", "none");
             $(this).parent().css("cursor", "no-drop");
         },
     });

 })(jQuery, window, document)

  

 

  

posted @ 2018-09-14 09:03  菲比月  阅读(2322)  评论(0编辑  收藏  举报