【问题标题】:Displaying a message when jQuery filter returns nothing当 jQuery 过滤器不返回任何内容时显示消息
【发布时间】:2019-04-14 03:58:25
【问题描述】:

我在网上找到了按文本内容过滤元素的代码。
不匹配时如何显示消息?

$("button").click(function() {
  var value = $(this).data('value').toUpperCase();
  $("div").filter(function(index) {
    $(this).toggle($(this).text().indexOf(value) > -1)
  });
});
<button>example</button>

【问题讨论】:

    标签: javascript jquery html filter


    【解决方案1】:

    您使用filter() 根据状态切换每个项目,例如使用each()。但是filter() 的一个优点是您可以返回减少的选择并计算其中包含的项目。该值可以确定是否应显示“不匹配”消息。

    ... .filter() 方法从匹配元素的子集构造一个新的 jQuery 对象。提供的选择器针对每个元素进行测试;与选择器匹配的所有元素都将包含在结果中。 -- filter().

    对于每个元素,如果函数返回 true(或“真实”值),则该元素将包含在过滤后的集合中;否则,它将被排除在外。 -- Using a Filter Function

    因此,与其直接从过滤器调用中切换项目,不如考虑返回当前项目是否匹配的布尔度量。将生成的过滤选择保存在变量中。过滤后,您可以整体切换该选择:

    var $filtered = $items.filter(function() {
      return $(this).text().indexOf(value) > -1;
    });
    
    $items.toggle(false);
    $filtered.toggle(true);
    

    这会隐藏所有项目,然后仅显示过滤后的项目。
    你甚至可以考虑一些淡入淡出的动画:

    $items.hide(250);
    $filtered.stop(true,false).show(250);
    

    然后您可以引用过滤后的选择的length
    如果为零,则显示“未找到”消息:

    var hasMatches = $filtered.length;
    
    if (hasMatches) {
      // there were matches.
    } else {
      // no matches.
    }
    

    您还可以将selector 传递给过滤器。 jQuery 的:contains() selector 选择“所有包含指定文本的元素”,这是一个不错的选择。

    工作示例:

    var $items = $('.item');
    var $none = $('#none');
    var fade = 250;
    
    function filterContent() {
    
      // get word from value of clicked button.
      var word = this.value;
    
      // hide items; filter; show filtered; count matches
      var hasMatches = $items
        .hide(fade)
        .filter(':contains(' + word + ')')
        .stop(true, false)
        .show(fade)
        .length;
    
      // if no matches, show message.
      if (hasMatches) {
        $none.hide(fade);
      } else {
        $none.show(fade);
      }
    
    }
    
    $('button').on('click', filterContent);
    #none {
      display: none;
      color: darkred;
    }
    
    #buttons {
      margin: 1em 0 0;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class="item">Here is some text.</div>
    <div class="item">Here is some other text.</div>
    <div class="item">Here is some other different text.</div>
    <div class="item">Here is something else.</div>
    <div class="item">Here is some additional text.</div>
    
    <div id="none">No matches found.</div>
    
    <nav id="buttons">
      <button type="button" value="">all</button>
      <button type="button" value="text">text</button>
      <button type="button" value="other">other</button>
      <button type="button" value="additional">additional</button>
      <button type="button" value="bazooka">bazooka</button>
    </nav>

    另一种方式:

    如果您愿意,您可以在过滤器内部切换,只要您仍然从函数返回布尔状态。我建议制作一个单独的函数来传递给过滤器。在这种情况下,toggleItem() 确定项目的状态(匹配或不匹配),根据该状态切换项目,然后返回状态。

    var $items = $('.item');
    var $none = $('#none');
    
    function toggleItem(word) {
      return function(k, el) {
        var $item = $(el);
        var state = $item.text().indexOf(word) > -1;
        $item.toggle(state);
        return state;
      }
    }
    
    function filterContent() {
    
      // get word from value of clicked button.
      var word = this.value;
    
      // filter while toggling and count result.
      var hasMatches = $items
        .filter(toggleItem(word))
        .length;
    
      // if no matches, show message.
      $none.toggle(!hasMatches);
    
    }
    
    $('button').on('click', filterContent);
    #none {
      display: none;
      color: darkred;
    }
    
    #buttons {
      margin: 1em 0 0;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class="item">Here is some text.</div>
    <div class="item">Here is some other text.</div>
    <div class="item">Here is some other different text.</div>
    <div class="item">Here is something else.</div>
    <div class="item">Here is some additional text.</div>
    
    <div id="none">No matches found.</div>
    
    <div id="buttons">
      <button type="button" value="">all</button>
      <button type="button" value="text">text</button>
      <button type="button" value="other">other</button>
      <button type="button" value="additional">additional</button>
      <button type="button" value="bazooka">bazooka</button>
    </div>

    在我看来,这有点难以阅读,并且不如链接的“隐藏、过滤、显示、长度”命令那么清晰,但这在某种程度上是一种风格问题。可见这个蛋糕的烤法有很多种!

    这个很短很甜:

    var $none = $("#none");
    var $items = $(".item");
    
    $("button").click(function() {
    
      var value = $(this).data('value');
    
      $items.each(function() {
        $(this).toggle($(this).text().indexOf(value) > -1);
      });
    
      $none.toggle(!$items.filter(':visible').length);
    
    });
    #none {
      display: none;
      color: darkred;
    }
    
    #buttons {
      margin: 1em 0 0;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class="item">Here is some text.</div>
    <div class="item">Here is some other text.</div>
    <div class="item">Here is some other different text.</div>
    <div class="item">Here is something else.</div>
    <div class="item">Here is some additional text.</div>
    
    <div id="none">No matches found.</div>
    
    <nav id="buttons">
      <button type="button" data-value="">all</button>
      <button type="button" data-value="text">text</button>
      <button type="button" data-value="other">other</button>
      <button type="button" data-value="additional">additional</button>
      <button type="button" data-value="bazooka">bazooka</button>
    </nav>

    【讨论】:

      【解决方案2】:

      您可以创建一个变量来计算匹配项。

      $("button").click(function(){
      var value = $(this).data('value').toUpperCase();
      var count = 0;
      $("div").filter(function(index) {
      
        if($(this).text().indexOf(value) > -1) count++;
      
        $(this).toggle($(this).text().indexOf(value) > -1)
      
        });
        if(count == 0) alert('Not match');
      });
      

      $("button").click(function(){
      var value = $(this).data('value').toUpperCase();
      var count = 0;
      $("div").filter(function(index) {
      
        if($(this).text().indexOf(value) > -1) count++;
        
        $(this).toggle($(this).text().indexOf(value) > -1)
        
        });
        if(count == 0) alert('Not match');
      });
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <div>TEST1</div>
      <div>example</div>
      <div>test1</div>
      
      
      <button data-value='test1'>example</button>

      【讨论】:

        【解决方案3】:

        filter() 返回值。检查长度是否为 1 或更多。

        $(".filter").click(function() {
          var value = $(this).text(); //Get the text of the button
          var result = $("div").hide().filter(function(i, o) { //Hide All and filter
            return $(o).text().includes(value); //Return true if the content of div contains text of the button
          }).show(); //Show all result
        
        
          if (result.length) { //Check the length of the result
            //Found match/es
            $(".msg").text('');
          } else {
            //No match
            $(".msg").text(`${value} not found`);
          }
        });
        
        $(".show-all").click(function() {
          $("div").show();
        });
        .msg {
          border: 1px solid black;
        }
        
        div {
          background-color: pink
        }
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        
        <span class="msg"></span>
        
        <br /><br />
        
        <div> apple </div>
        <div> orange </div>
        <div> rock melon</div>
        <div> pineapple </div>
        <div> pineapple pie</div>
        
        <br /><br />
        
        <button class="filter">example</button>
        <button class="filter">pineapple</button>
        <button class="filter">rock</button>
        
        <br /><br />
        
        <button class="show-all">Show all</button>

        【讨论】:

        • 很奇怪。看来sn-p控制台在&lt;body&gt;里面,所以console.log()输出的文本会被div过滤器匹配,导致结果混乱。
        猜你喜欢
        • 2014-02-26
        • 2010-11-20
        • 1970-01-01
        • 2012-02-14
        • 1970-01-01
        • 1970-01-01
        • 2021-12-12
        • 2020-03-02
        • 1970-01-01
        相关资源
        最近更新 更多