带搜索框的jQuery下拉框插件

来源:互联网 发布:apache linux 下载 编辑:程序博客网 时间:2024/05/21 10:48

由于下拉框的条数有几十个,于是打算找一个可以搜索查找功能的下拉框,刚开始在网上看了几个,都是有浏览器兼容性问题,后来看到这个“带搜索框的jQuery下拉框美化插件 searchable”,看演示代码简单易用,支持多个浏览器。

不过在使用过程中碰到了几个问题,先后解决了。

1、多个下拉框放在一起会出现遮挡的问题,原文评论有个解决方法:
在jquery.searchableSelect.js文件里面的代码里面加上下面2行带注释的代码

show: function() {    this.dropdown.removeClass('searchable-select-hide');    this.input.focus();    this.status = 'show';    this.setPriviousAndNextVisibility();    this.dropdown.css('z-index', 100); //打开下拉列表时调高z-index层级  }, hide: function() {    if (!(this.status === 'show')) return;    if (this.items.find(':not(.searchable-select-hide)').length === 0) this.input.val('');    this.dropdown.addClass('searchable-select-hide');    this.searchableElement.trigger('focus');    this.status = 'hide';    this.dropdown.css('z-index', 1); //关闭下拉列表时恢复z-index层级  },
2、原文用的是jquery-1.11.1.min.js,但是整个项目用的是jquery-1.7.2.js,在chrome浏览器F12调试一加载页面会出现错误信息:

Uncaught TypeError: $.expr.createPseudo is not a function
$(...).searchableSelect is not a function
点进去提示$.expr.createPseudo有语法错误
猜测是jquery版本问题,果然,搜索了一下,$.expr.createPseudo是jquery1.8.1版本以上支持的。
于是修改了下代码,把下面代码

$.expr[":"].searchableSelectContains = $.expr.createPseudo(function(arg) {  return function( elem ) {    return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;  };});

修改为下面就解决:

$.expr[":"].searchableSelectContains = function(obj,index,meta){ return $(obj).text().toUpperCase().indexOf(meta[3].toUpperCase()) >= 0;};

3、第2个问题解决后,发现在删除搜索框文字为空时,chrome调试窗口有异常,并且下拉框不会恢复原来的下拉选项

调试是下面这句代码有问题(如果是demo中的jquery-1.11.1.min.js版本,则不存在此问题)
this.items.find('.searchable-select-item:searchableSelectContains('+text+')').removeClass('searchable-select-hide');
解决方法是加一个是否为空的判断:

if(text != ''){this.items.find('.searchable-select-item:searchableSelectContains('+text+')').removeClass('searchable-select-hide');}else{this.items.find('.searchable-select-item').removeClass('searchable-select-hide');  }
4、把功能整合到项目时,发现下拉框里面的搜索框被拉长变形了,chromeF12调试窗口能看到搜索框的样式有删除线,即被优先级更高的样式替换了。

解决方法是修改jquery.searchableSelect.css里面的样式,加一个!important提高优先级

.searchable-select-input {  margin-top: 5px;  border: 1px solid #ccc!important;  outline: none;  padding: 4px;  width: 100%!important;  box-sizing: border-box;  }


附,修改后的代码:

demo.html

 <!DOCTYPE html>

<html>  <head>    <meta http-equiv="content-type" content="text/html; charset=utf-8">    <title>带搜索框的jQuery下拉框美化插件 searchableSelect</title>    <link href="jquery.searchableSelect.css" rel="stylesheet" type="text/css">    <script src="jquery-1.7.2.js"></script>    <script src="jquery.searchableSelect.js"></script>  </head>  <body>    <select id="se1">  <option value="">请选择</option>      <option value="jQuery插件库">jQuery插件库</option>      <option value="BlackBerry">BlackBerry</option>      <option value="device">device</option>      <option value="with">with</option>      <option value="entertainment">entertainment</option>      <option value="and">and</option>      <option value="social">social</option>      <option value="networking">networking</option>      <option value="apps">apps</option>      <option value="or">or</option>      <option value="apps">apps</option>      <option value="that">that</option>    </select>    <input type="button" value="test" onclick="var v = $('#se1').val();alert(v);" />    <script>$(function(){$('#se1').searchableSelect();});    </script>  </body></html>

jquery.searchableSelect.js

// Author: David Qin// E-mail: david@hereapp.cn// Date: 2014-11-05(function($){   //jQuery1.8.1以上版本使用  // a case insensitive jQuery :contains selector  /*$.expr[":"].searchableSelectContains = $.expr.createPseudo(function(arg) {    return function( elem ) {      return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;    };  });*/    $.expr[":"].searchableSelectContains = function(obj,index,meta){ return $(obj).text().toUpperCase().indexOf(meta[3].toUpperCase()) >= 0;  };    $.searchableSelect = function(element, options) {    this.element = element;    this.options = options || {};    this.init();    var _this = this;    this.searchableElement.click(function(event){      // event.stopPropagation();      _this.show();    }).on('keydown', function(event){      if (event.which === 13 || event.which === 40 || event.which == 38){        event.preventDefault();        _this.show();      }    });    $(document).on('click', null, function(event){      if(_this.searchableElement.has($(event.target)).length === 0)        _this.hide();    });    this.input.on('keydown', function(event){      event.stopPropagation();      if(event.which === 13){         //enter        event.preventDefault();        _this.selectCurrentHoverItem();        _this.hide();      } else if (event.which == 27) { //ese        _this.hide();      } else if (event.which == 40) { //down        _this.hoverNextItem();      } else if (event.which == 38) { //up        _this.hoverPreviousItem();      }    }).on('keyup', function(event){      if(event.which != 13 && event.which != 27 && event.which != 38 && event.which != 40)        _this.filter();    })  }  var $sS = $.searchableSelect;  $sS.fn = $sS.prototype = {    version: '0.0.1'  };  $sS.fn.extend = $sS.extend = $.extend;  $sS.fn.extend({    init: function(){      var _this = this;      this.element.hide();      this.searchableElement = $('<div tabindex="0" class="searchable-select"></div>');      this.holder = $('<div class="searchable-select-holder"></div>');      this.dropdown = $('<div class="searchable-select-dropdown searchable-select-hide"></div>');      this.input = $('<input type="text" class="searchable-select-input" />');      this.items = $('<div class="searchable-select-items"></div>');      this.caret = $('<span class="searchable-select-caret"></span>');      this.scrollPart = $('<div class="searchable-scroll"></div>');      this.hasPrivious = $('<div class="searchable-has-privious">...</div>');      this.hasNext = $('<div class="searchable-has-next">...</div>');      this.hasNext.on('mouseenter', function(){        _this.hasNextTimer = null;        var f = function(){          var scrollTop = _this.items.scrollTop();          _this.items.scrollTop(scrollTop + 20);          _this.hasNextTimer = setTimeout(f, 50);        }        f();      }).on('mouseleave', function(event) {        clearTimeout(_this.hasNextTimer);      });      this.hasPrivious.on('mouseenter', function(){        _this.hasPriviousTimer = null;        var f = function(){          var scrollTop = _this.items.scrollTop();          _this.items.scrollTop(scrollTop - 20);          _this.hasPriviousTimer = setTimeout(f, 50);        }        f();      }).on('mouseleave', function(event) {        clearTimeout(_this.hasPriviousTimer);      });      this.dropdown.append(this.input);      this.dropdown.append(this.scrollPart);      this.scrollPart.append(this.hasPrivious);      this.scrollPart.append(this.items);      this.scrollPart.append(this.hasNext);      this.searchableElement.append(this.caret);      this.searchableElement.append(this.holder);      this.searchableElement.append(this.dropdown);      this.element.after(this.searchableElement);      this.buildItems();      this.setPriviousAndNextVisibility();    },    filter: function(){      var text = this.input.val();      this.items.find('.searchable-select-item').addClass('searchable-select-hide');  if(text != ''){this.items.find('.searchable-select-item:searchableSelectContains('+text+')').removeClass('searchable-select-hide');  }else{this.items.find('.searchable-select-item').removeClass('searchable-select-hide');   }      if(this.currentSelectedItem.hasClass('searchable-select-hide') && this.items.find('.searchable-select-item:not(.searchable-select-hide)').length > 0){        this.hoverFirstNotHideItem();      }      this.setPriviousAndNextVisibility();    },    hoverFirstNotHideItem: function(){      this.hoverItem(this.items.find('.searchable-select-item:not(.searchable-select-hide)').first());    },    selectCurrentHoverItem: function(){      if(!this.currentHoverItem.hasClass('searchable-select-hide'))        this.selectItem(this.currentHoverItem);    },    hoverPreviousItem: function(){      if(!this.hasCurrentHoverItem())        this.hoverFirstNotHideItem();      else{        var prevItem = this.currentHoverItem.prevAll('.searchable-select-item:not(.searchable-select-hide):first')        if(prevItem.length > 0)          this.hoverItem(prevItem);      }    },    hoverNextItem: function(){      if(!this.hasCurrentHoverItem())        this.hoverFirstNotHideItem();      else{        var nextItem = this.currentHoverItem.nextAll('.searchable-select-item:not(.searchable-select-hide):first')        if(nextItem.length > 0)          this.hoverItem(nextItem);      }    },    buildItems: function(){      var _this = this;      this.element.find('option').each(function(){        var item = $('<div class="searchable-select-item" data-value="'+$(this).attr('value')+'">'+$(this).text()+'</div>');        if(this.selected){          _this.selectItem(item);          _this.hoverItem(item);        }        item.on('mouseenter', function(){          $(this).addClass('hover');        }).on('mouseleave', function(){          $(this).removeClass('hover');        }).click(function(event){          event.stopPropagation();          _this.selectItem($(this));          _this.hide();        });        _this.items.append(item);      });      this.items.on('scroll', function(){        _this.setPriviousAndNextVisibility();      })    },    show: function(){      this.dropdown.removeClass('searchable-select-hide');      this.input.focus();      this.status = 'show';      this.setPriviousAndNextVisibility();      this.dropdown.css('z-index', 100); //打开下拉列表时调高z-index层级    },    hide: function(){      if(!(this.status === 'show'))        return;      if(this.items.find(':not(.searchable-select-hide)').length === 0)          this.input.val('');      this.dropdown.addClass('searchable-select-hide');      this.searchableElement.trigger('focus');      this.status = 'hide';      this.dropdown.css('z-index', 1); //关闭下拉列表时恢复z-index层级    },    hasCurrentSelectedItem: function(){      return this.currentSelectedItem && this.currentSelectedItem.length > 0;    },    selectItem: function(item){      if(this.hasCurrentSelectedItem())        this.currentSelectedItem.removeClass('selected');      this.currentSelectedItem = item;      item.addClass('selected');      this.hoverItem(item);      this.holder.text(item.text());      var value = item.data('value');      this.holder.data('value', value);      this.element.val(value);      if(this.options.afterSelectItem){        this.options.afterSelectItem.apply(this);      }    },    hasCurrentHoverItem: function(){      return this.currentHoverItem && this.currentHoverItem.length > 0;    },    hoverItem: function(item){      if(this.hasCurrentHoverItem())        this.currentHoverItem.removeClass('hover');      if(item.outerHeight() + item.position().top > this.items.height())        this.items.scrollTop(this.items.scrollTop() + item.outerHeight() + item.position().top - this.items.height());      else if(item.position().top < 0)        this.items.scrollTop(this.items.scrollTop() + item.position().top);      this.currentHoverItem = item;      item.addClass('hover');    },    setPriviousAndNextVisibility: function(){      if(this.items.scrollTop() === 0){        this.hasPrivious.addClass('searchable-select-hide');        this.scrollPart.removeClass('has-privious');      } else {        this.hasPrivious.removeClass('searchable-select-hide');        this.scrollPart.addClass('has-privious');      }      if(this.items.scrollTop() + this.items.innerHeight() >= this.items[0].scrollHeight){        this.hasNext.addClass('searchable-select-hide');        this.scrollPart.removeClass('has-next');      } else {        this.hasNext.removeClass('searchable-select-hide');        this.scrollPart.addClass('has-next');      }    }  });  $.fn.searchableSelect = function(options){    this.each(function(){      var sS = new $sS($(this), options);    });    return this;  };})(jQuery);
jquery.searchableSelect.css

/*Author: David QinE-mail: david@hereapp.cnDate: 2014-11-05*/.searchable-select-hide {  display: none;}.searchable-select {  display: inline-block;  min-width: 130px;  font-size: 14px;  line-height: 1.428571429;  color: #555;  vertical-align: middle;  position: relative;  outline: none;  }.searchable-select-holder{  padding: 2px;  background-color: #fff;  background-image: none;  border: 1px solid #ccc;  border-radius: 2px;  min-height: 30px;  box-sizing: border-box;  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);  box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);  -webkit-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;  transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;}.searchable-select-caret {  position: absolute;  width: 0;  height: 0;  box-sizing: border-box;  border-color: black transparent transparent transparent;  top: 0;  bottom: 0;  border-style: solid;  border-width: 5px;  margin: auto;  right: 10px;}.searchable-select-dropdown {  position: absolute;  background-color: #fff;  border: 1px solid #ccc;  border-bottom-left-radius: 4px;  border-bottom-right-radius: 4px;  padding: 4px;  border-top: none;  top: 28px;  left: 0;  right: 0;}.searchable-select-input {  margin-top: 5px;  border: 1px solid #ccc;  outline: none;  padding: 4px;  width: 100%;  box-sizing: border-box;  width: 100%;}.searchable-scroll {  margin-top: 4px;  position: relative;}.searchable-scroll.has-privious {  padding-top: 16px;}.searchable-scroll.has-next {  padding-bottom: 16px;}.searchable-has-privious {  top: 0;}.searchable-has-next {  bottom: 0;}.searchable-has-privious, .searchable-has-next {  height: 16px;  left: 0;  right: 0;  position: absolute;  text-align: center;  z-index: 10;  background-color: white;  line-height: 8px;  cursor: pointer;}.searchable-select-items {  max-height: 400px;  overflow-y: scroll;  position: relative;}.searchable-select-items::-webkit-scrollbar {  display: none;}.searchable-select-item {  padding: 5px 5px;  cursor: pointer;  min-height: 30px;  box-sizing: border-box;    transition: all 1s ease 0s;}.searchable-select-item.hover {  background: #555;  color: white;}.searchable-select-item.selected {  background: #28a4c9;  color: white;}


原创粉丝点击