【问题标题】:How to dynamic filter options of <select > with jQuery?如何使用 jQuery 动态过滤 <select > 的选项?
【发布时间】:2010-11-29 16:23:41
【问题描述】:
<select >
<option value="something">something</option>
<option value="something_else">something else</option>
</select>
<input type="text" >

这样当用户输入内容时,只会显示与输入值匹配的选项。

【问题讨论】:

    标签: javascript jquery dom


    【解决方案1】:

    示例 HTML:

    //jQuery extension method:
    jQuery.fn.filterByText = function(textbox) {
      return this.each(function() {
        var select = this;
        var options = [];
        $(select).find('option').each(function() {
          options.push({
            value: $(this).val(),
            text: $(this).text()
          });
        });
        $(select).data('options', options);
    
        $(textbox).bind('change keyup', function() {
          var options = $(select).empty().data('options');
          var search = $.trim($(this).val());
          var regex = new RegExp(search, "gi");
    
          $.each(options, function(i) {
            var option = options[i];
            if (option.text.match(regex) !== null) {
              $(select).append(
                $('<option>').text(option.text).val(option.value)
              );
            }
          });
        });
      });
    };
    
    // You could use it like this:
    
    $(function() {
      $('select').filterByText($('input'));
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <select>
      <option value="hello">hello</option>
      <option value="world">world</option>
      <option value="lorem">lorem</option>
      <option value="ipsum">ipsum</option>
      <option value="lorem ipsum">lorem ipsum</option>
    </select>
    <input type="text">

    现场演示: http://www.lessanvaezi.com/filter-select-list-options/

    【讨论】:

    • 非常感谢您的 sn-p。这为我在一个小项目上节省了很多时间 - 就像一个魅力!
    • 这很好,但在我的情况下,过滤器文本框可能会在加载页面后立即包含一些文本。如何在加载页面后立即启动过滤?
    • 找到了! $('input').change();
    • 在所有浏览器中都能完美运行,包括 IE 7、8、9。谢谢。
    • 如果您尝试使用大型列表并在开始输入之前向下滚动,则会导致奇怪的状态(无论如何在 Chrome 中)。要解决此问题,您可以在第 11 行的 .empty() 之后添加 .scrollTop(0)
    【解决方案2】:

    我不确定为什么您有多个具有相同值的选项,但这可行

    $(document).ready(function() {
      $('input').change(function() {
        var filter = $(this).val();
        $('option').each(function() {
          if ($(this).val() == filter) {
            $(this).show();
          } else {
            $(this).hide();
          }
          $('select').val(filter);
        })
      })
    })
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <select>
       <option value="something1">something1</option>
       <option value="something1">something1</option>
       <option value="something2">something2</option>
       <option value="something2">something2</option>
       <option value="something2">something2</option>
       <option value="something3">something3</option>
       <option value="something3">something3</option>
       <option value="something3">something3</option>
    </select>
    <input type="text" placeholder="something1">

    【讨论】:

    【解决方案3】:

    与所有其他的略有不同,但我认为这是最简单的:

    $(document).ready(function(){
    
        var $this, i, filter,
            $input = $('#my_other_id'),
            $options = $('#my_id').find('option');
    
        $input.keyup(function(){
            filter = $(this).val();
            i = 1;
            $options.each(function(){
                $this = $(this);
                $this.removeAttr('selected');
                if ($this.text().indexOf(filter) != -1) {
                    $this.show();
                    if(i == 1){
                        $this.attr('selected', 'selected');
                    }
                    i++;
                } else {
                    $this.hide();
                }
            });
        });
    
    });
    

    【讨论】:

    • Mottie 和 Hersker 的混合体
    【解决方案4】:

    与大多数其他解决方案相比,代码要简单得多。查找文本(不区分大小写)并使用 CSS 隐藏/显示内容。比存储数据副本要好得多。

    将选择框的 id 和包含过滤器的输入的 id 传递给此方法。

    function FilterSelectList(selectListId, filterId)
    {
        var filter = $("#" + filterId).val();
        filter = filter.toUpperCase();
    
        var options = $("#" + selectListId + " option");
        for (var i = 0; i < options.length; i++)
        {
           if (options[i].text.toUpperCase().indexOf(filter) < 0)
               $(options[i]).css("display", "none");
           else
               $(options[i]).css("display", "block");
        }
    };
    

    【讨论】:

      【解决方案5】:

      这是一个简单的解决方案,您可以克隆列表选项并将它们保存在一个对象中以供以后恢复。脚本清除列表并仅添加包含输入文本的选项。这也应该跨浏览器工作。我从这篇文章中得到了一些帮助:https://stackoverflow.com/a/5748709/542141

      HTML

      <input id="search_input" placeholder="Type to filter">
      <select id="theList" class="List" multiple="multiple">
      

      或剃须刀

      @Html.ListBoxFor(g => g.SelectedItem, Model.items, new { @class = "List", @id = "theList" })
      

      脚本

      <script type="text/javascript">
        $(document).ready(function () {
          //copy options
          var options = $('#theList option').clone();
          //react on keyup in textbox
          $('#search_input').keyup(function () {
            var val = $(this).val();
            $('#theList').empty();
            //take only the options containing your filter text or all if empty
            options.filter(function (idx, el) {
              return val === '' || $(el).text().indexOf(val) >= 0;
            }).appendTo('#theList');//add it to list
           });
        });
      </script>
      

      【讨论】:

        【解决方案6】:

        更新 Lessan 的答案以保留选项的属性。

        这是我第一次在 Stack Overflow 上回答,所以不确定我应该编辑他的答案还是创建自己的答案。

        jQuery.fn.allAttr = function() {
          var a, aLength, attributes, map;
          if (!this[0]) return null;
          if (arguments.length === 0) {
            map = {};
            attributes = this[0].attributes;
            aLength = attributes.length;
            for (a = 0; a < aLength; a++) {
              map[attributes[a].name.toLowerCase()] = attributes[a].value;
            }
            return map;
          } else {
            for (var propin arguments[0]) {
              $(this[0]).attr(prop, arguments[0][prop]);
            }
            return this[0];
          }
        };
        
        
        jQuery.fn.filterByText = function(textbox) {
          return this.each(function() {
            var select = this;
            var options = [];
            $(select).find('option').each(function() {
              options.push({ value: $(this).val(), 
                text: $(this).text(), 
                allAttr: $(this).allAttr() });
            });
            $(select).data('options', options);
        
            $(textbox).bind('change keyup', function() {
              var search = $.trim($(this).val());
              var regex = new RegExp(search, "gi");
        
              $.each($(select).empty().data('options'), function(i, option) {
                if (option.text.match(regex) !== null) {
                  $(select).append(
                    $('<option>').text(option.text)
                    .val(option.value)
                    .allAttr(option.allAttr)
                  );
                }
              });
            });
          });
        };
        

        【讨论】:

        • 隐藏你不想要的会容易得多。
        【解决方案7】:

        我遇到了与此类似的问题,因此我更改了接受的答案以制作更通用的函数版本。我想我会把它留在这里。

        var filterSelectOptions = function($select, callback) {
        
            var options = null,
                dataOptions = $select.data('options');
        
            if (typeof dataOptions === 'undefined') {
                options = [];
                $select.children('option').each(function() {
                    var $this = $(this);
                    options.push({value: $this.val(), text: $this.text()});
                });
                $select.data('options', options);
            } else {
                options = dataOptions;
            }
        
            $select.empty();
        
            $.each(options, function(i) {
                var option = options[i];
                if(callback(option)) {
                    $select.append(
                        $('<option/>').text(option.text).val(option.value)
                    );
                }
            });
        };
        

        【讨论】:

          【解决方案8】:
          <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
          <script language='javascript'>
          jQuery.fn.filterByText = function(textbox, selectSingleMatch) {
            return this.each(function() {
              var select = this;`enter code here`
              var options = [];
              $(select).find('option').each(function() {
                options.push({value: $(this).val(), text: $(this).text()});
              });
              $(select).data('options', options);
              $(textbox).bind('change keyup', function() {
                var options = $(select).empty().scrollTop(0).data('options');
                var search = $.trim($(this).val());
                var regex = new RegExp(search,'gi');
          
                $.each(options, function(i) {
                  var option = options[i];
                  if(option.text.match(regex) !== null) {
                    $(select).append(
                       $('<option>').text(option.text).val(option.value)
                    );
                  }
                });
                if (selectSingleMatch === true && 
                    $(select).children().length === 1) {
                  $(select).children().get(0).selected = true;
                }
              });
            });
          };
          
            $(function() {
               $('#selectorHtmlElement').filterByText($('#textboxFiltr2'), true);
            });
          </script>
          

          【讨论】:

          • jQuery.fn.filterByText 对我来说是未定义的,这在更新到 jquery.3.5.1.min.js 时开始。我缺少的任何东西。
          【解决方案9】:

          您可以使用 select2 插件来创建这样的过滤器。有了这么多的编码工作就可以避免。你可以从https://select2.github.io/获取插件

          这个插件应用起来非常简单,甚至可以轻松完成高级工作。 :)

          【讨论】:

            【解决方案10】:

            使用 Aaron 的回答,这可能是最简单的解决方案:

            function filterSelectList(selectListId, filterId)
            {
                var filter = $("#" + filterId).val().toUpperCase();
            
                $("#" + selectListId + " option").each(function(i){
                   if ($(this).text.toUpperCase().includes(filter))
                       $(this).css("display", "block");
                   else
                       $(this).css("display", "none");
                });
            };
            

            【讨论】:

              【解决方案11】:

              现在更简单的方法是使用 jquery filter(),如下所示:

              var options = $('select option');
              var query = $('input').val();
              options.filter(function() {
                  $(this).toggle($(this).val().toLowerCase().indexOf(query) > -1);
              });  
              

              【讨论】:

              • 我首先尝试了这个答案,因为它看起来干净简单,但它只适用于 Chrome。在 IE 11 中根本不起作用,并在 Edge 中引起了一些奇怪的行为。
              【解决方案12】:

              只需对 Lessan Vaezi 的上述出色答案稍作修改。我遇到了需要在选项条目中包含属性的情况。原始实现会丢失任何标签属性。上述答案的这个版本保留了选项标签属性:

              jQuery.fn.filterByText = function(textbox) {
                return this.each(function() {
                  var select = this;
                  var options = [];
                  $(select).find('option').each(function() {
                    options.push({
                        value: $(this).val(),
                        text: $(this).text(),
                        attrs: this.attributes, // Preserve attributes.
                    });
                  });
                  $(select).data('options', options);
              
                  $(textbox).bind('change keyup', function() {
                    var options = $(select).empty().data('options');
                    var search = $.trim($(this).val());
                    var regex = new RegExp(search, "gi");
              
                    $.each(options, function(i) {
                      var option = options[i];
                      if (option.text.match(regex) !== null) { 
                          var new_option = $('<option>').text(option.text).val(option.value);
                          if (option.attrs) // Add old element options to new entry
                          {
                              $.each(option.attrs, function () {
                                  $(new_option).attr(this.name, this.value);
                                  });
                          }
                          
                          $(select).append(new_option);
                      }
                    });
                  });
                });
              };
              

              【讨论】:

                【解决方案13】:

                给定一个 ID 为 #filter_keyword

                的文本类型输入

                还有一个您之前填充的 ID 为 #all_keywords 的选择

                $(document).on('input', '#filter_keyword', function(event){
                    var kw=$(this).val();
                    $('#all_keywords > option').each(function() {
                        if ( kw.length > 0 && this.text.replace(kw, '') == this.text )
                        {
                            $(this).hide();
                        } else {
                            $(this).show();                                 
                        }
                    });
                });
                

                就是这样。

                【讨论】:

                  【解决方案14】:

                  您的解决方案缺少在 RegExp 中使用的转义字符串以便更好地使用。

                  function escapeRegExp(string) {
                    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
                  }
                  

                  https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-03-30
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-08-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多