• js在前端实现一个下拉搜索的功能


    searchableSelect.js

    (function($){
      // 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);
    

      

    searchableSelect.css

    /* select */
    
    .searchable-select-hide {
      display: none;
    }
    
    .searchable-select {
      display: inline-block;
      min- 100%;
      font-size: 14px;
      line-height: 1.428571429;
      color: #555;
      vertical-align: middle;
      position: relative;
      outline: none;
      z-index: 9
    }
    
    .searchable-select-holder{
      padding: 0 10px;
      background-color: #fff;
      background-image: none;
      border: 1px solid #d9d9d9;
      min-height: 36px;
      line-height: 36px;
      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;
       0;
      height: 0;
      box-sizing: border-box;
      border-color: #a0a0a0 transparent transparent transparent;
      top: 5px;
      bottom: 0;
      border-style: solid;
      border- 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;
       100%;
      box-sizing: border-box;
       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.selected,
    .searchable-select-item.hover {
      background: #3f86d8;
      color: white;
    }
    /* select */

    引入css文件

    <link rel="stylesheet" href="{% static 'css/selectSearch/searchableSelect.css' %}" type="text/css" />

    引入js文件

    <script type="text/javascript" src="{% static 'js/selectSearch/searchableSelect.js' %}"></script>

    html

                                <label class="col-sm-2 control-label">选项1:</label>
                                <div class="col-md-4">
                                    <select id="dep_onwer" name="dep_onwer" class="selectpicker show-tick form-control" data-live-search="true" title="请选择">
                                    </select>
    
                                </div>
    
                                <label class="col-sm-2 control-label">选项2:</label>
                                <div class="col-md-4">
                                    <select id="operation_owner" name="operation_owner" class="selectpicker show-tick form-control" data-live-search="true">
                                    </select>
    
                                </div>

    选项1。js

                // 页面加载时,获取列表1
                $(document).ready(function(){
                    $ajax({
                        url: '',
                        data: {},
                        type: "GET",
                        success: function (data) {
                            if (data.result == false) {
                           } else{
                                // 赋值给下拉框
                                {#console.log(data.message)#}
                                var dept = document.getElementById("dep_onwer"); //dep_onwer是select的id标识
                                var init_op = new Option("--请选择--", 0);
                                dept.options.add(init_op);
                                for(i=0; i<data.message.length; i++){
                                    var op = new Option(data.message[i]['name'], data.message[i]['id']);
                                    dept.options.add(op);
                                    }
                                $('#dep_onwer').searchableSelect();
                                }
                            }
                        });
                });

    选项2。 js

               $("#dep_onwer").change(function(){
                    var dep_onwer_id=$("#dep_onwer option:selected");
                    console.log(dep_onwer_id.val())
                    simple_ajax({
                        url: '',
                        data: {
                            "id": dep_onwer_id.val()
                        },
                        type: "GET",
                        success: function (data) {
                        if (data.result == false) {
                            alert(data.message);
                        } else{
                            $("#operation_owner + div").remove();   //这里是因为跟选项1联动,searchableSelect里会重新将select转化成1个div,如果这里不删除的话,则会出现多个选项2
                            var owner = document.getElementById("operation_owner"); //operation_owner是select的id标识
                            owner.options.length = 0  //这里是清除一下选项2的列表,否则来回点选项1,则选项2会一直累加,造成信息错乱
                            var init_op = new Option("--请选择--", 0);
                            owner.options.add(init_op);
                            for(i=0; i<data.message.length; i++){
                                var op = new Option(data.message[i]['name'], data.message[i]['id']);
                                owner.options.add(op);
                                }
                            $('#operation_owner').searchableSelect();
                            }
                        },
                    });
                });

    在这里值得一提的地方是,

    searchableSelect.js不支持onchange事件,需要在原js文件里的selectItem函数里加上这个方法:this.element.trigger('change');

     大功告成



  • 相关阅读:
    研究称90%的癌症由非健康生活习惯导致
    章苏阳:早期投资,第一是看人,第二也是看人,第三还是看人!
    文章翻译第七章7-9
    文章翻译第七章4-6
    文章翻译第六章1-3
    翻译文章第六章8-11
    文章翻译第七章10-12
    VR虚拟现实技术在教育领域的前景展望
    围棋比赛不算什么,更牛的是机器人能预测未来
    c语言简单实现word count功能
  • 原文地址:https://www.cnblogs.com/lutt/p/15969705.html
Copyright © 2020-2023  润新知