代码之家  ›  专栏  ›  技术社区  ›  Millhorn

如何使用JavaScript过滤器过滤元素?

  •  1
  • Millhorn  · 技术社区  · 6 年前

    我正在努力让这个过滤器正常工作。

    我将它设置为根据卡片标题(h5)过滤并仅显示搜索到的内容。它过滤掉了不需要的标题,但没有过滤掉卡的其他部分。

    为了更好的解释,这里有一个演示- JS Element Filter

    代码如下:

    function myFunction() {
        var input, filter, card, h5, a, i;
        input = document.getElementById("myFilter");
        filter = input.value.toUpperCase();
        card = document.getElementById("myItems");
        h5 = card.getElementsByTagName("h5");
        for (i = 0; i < h5.length; i++) {
            a = h5[i].getElementsByTagName("a")[0];
            if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
                h5[i].style.display = "";
            } else {
                h5[i].style.display = "none";
            }
        }
    }
    .container {
      padding: 10px;
    }
    
    ul li {
      list-style: none;
      
    }
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <div class="container">
      <div class="row">
        <div class="col-sm-12 mb-3">
          <input type="text" id="myFilter" class="form-control" onkeyup="myFunction()" placeholder="Search for names..">
        </div>
      </div>
      <div class="row" id="myItems">
        <div class="col-sm-12 mb-3">
          <div class="card">
            <div class="card-body">
              <h5 class="card-title"><a href="#">Card One</a></h5>
              <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
              <p class="card-text">Some text.</p>
            </div>
          </div>
    
          <div class="card">
            <div class="card-body">
              <h5 class="card-title"><a href="#">Card Two</a></h5>
              <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
              <p class="card-text">Some text.</p>
            </div>
          </div>
    
          <div class="card">
            <div class="card-body">
              <h5 class="card-title"><a href="#">Card Three</a></h5>
              <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
              <p class="card-text">Some text.</p>
            </div>
          </div>      
        </div>    
      </div>
    </div> 
    4 回复  |  直到 6 年前
        1
  •  1
  •   Damiaan Dufaux    6 年前

    原因

    你只是在隐藏标题( h5.card-title )而不是整张卡片( div.card )

    解决方案

    首先要得到整张卡片的参考。然后隐藏该元素而不仅仅是标题。

    实施A

    一个快速而肮脏的方法是通过 parentElement 财产。因为你的父母 <h5> card-body 它的父母是你通过它获得的全部卡片 h5[i].parentElement.parentElement .

    所以改变 h5[i].style.display h5[i].parentElement.parentElement.style.display 这样地:

    function myFunction() {
        var input, filter, card, h5, a, i;
        input = document.getElementById("myFilter");
        filter = input.value.toUpperCase();
        card = document.getElementById("myItems");
        h5 = card.getElementsByTagName("h5");
        for (i = 0; i < h5.length; i++) {
            a = h5[i].getElementsByTagName("a")[0];
            if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
                h5[i].parentElement.parentElement.style.display = "";
            } else {
                h5[i].parentElement.parentElement.style.display = "none";
            }
        }
    }
    .container {
      padding: 10px;
    }
    
    ul li {
      list-style: none;
      
    }
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <div class="container">
      <div class="row">
        <div class="col-sm-12 mb-3">
          <input type="text" id="myFilter" class="form-control" onkeyup="myFunction()" placeholder="Search for names..">
        </div>
      </div>
      <div class="row" id="myItems">
        <div class="col-sm-12 mb-3">
          <div class="card">
            <div class="card-body">
              <h5 class="card-title"><a href="#">Card One</a></h5>
              <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
              <p class="card-text">Some text.</p>
            </div>
          </div>
    
          <div class="card">
            <div class="card-body">
              <h5 class="card-title"><a href="#">Card Two</a></h5>
              <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
              <p class="card-text">Some text.</p>
            </div>
          </div>
    
          <div class="card">
            <div class="card-body">
              <h5 class="card-title"><a href="#">Card Three</a></h5>
              <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
              <p class="card-text">Some text.</p>
            </div>
          </div>      
        </div>    
      </div>
    </div> 

    实施B

    一个更健壮的解决方案是遍历卡片而不是标题。这样你就可以直接引用卡片,而不必修改parentElements。当您只想搜索文本时,使用 innerText 属性访问卡标题中的文本字符串。

    function myFunction() {
        var input, filter, cards, cardContainer, h5, title, i;
        input = document.getElementById("myFilter");
        filter = input.value.toUpperCase();
        cardContainer = document.getElementById("myItems");
        cards = cardContainer.getElementsByClassName("card");
        for (i = 0; i < cards.length; i++) {
            title = cards[i].querySelector(".card-body h5.card-title a");
            if (title.innerText.toUpperCase().indexOf(filter) > -1) {
                cards[i].style.display = "";
            } else {
                cards[i].style.display = "none";
            }
        }
    }
    .container {
      padding: 10px;
    }
    
    ul li {
      list-style: none;
    }
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <div class="container">
      <div class="row">
        <div class="col-sm-12 mb-3">
          <input type="text" id="myFilter" class="form-control" onkeyup="myFunction()" placeholder="Search for names..">
        </div>
      </div>
      <div class="row" id="myItems">
        <div class="col-sm-12 mb-3">
          <div class="card">
            <div class="card-body">
              <h5 class="card-title"><a href="#">Card One</a></h5>
              <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
              <p class="card-text">Some text.</p>
            </div>
          </div>
    
          <div class="card">
            <div class="card-body">
              <h5 class="card-title"><a href="#">Card Two</a></h5>
              <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
              <p class="card-text">Some text.</p>
            </div>
          </div>
    
          <div class="card">
            <div class="card-body">
              <h5 class="card-title"><a href="#">Card Three</a></h5>
              <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
              <p class="card-text">Some text.</p>
            </div>
          </div>      
        </div>    
      </div>
    </div>
        2
  •  0
  •   Juky    6 年前

    您必须隐藏整个卡容器,而不是只隐藏标题(h5)。 快速修正将使用 parentNode 例如,在标题上

    if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
        h5[i].parentNode.style.display = "";
    } else {
        h5[i].parentNode.style.display = "none";
    }
    
        3
  •  0
  •   Jack Wilkinson    6 年前

    问题是你只是 display:none 反之亦然 h5 而不是整张卡片本身。

    看这里

    function myFunction() {
        var input, filter, card, h5, a, i;
        input = document.getElementById("myFilter");
        filter = input.value.toUpperCase();
        card = document.getElementById("myItems");
        h5 = card.getElementsByTagName("h5");
        for (i = 0; i < h5.length; i++) {
            a = h5[i].getElementsByTagName("a")[0];
            if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
                h5[i].closest(".card").style.display = "";
            } else {
                h5[i].closest(".card").style.display = "none";
            }
        }
    }

    我已经把它改了,这样它就有了它最近的父母 .card 在这里

    h5[i].closest(".card")

    或者,如果目标浏览器不支持 .closest 你可以用

    h5[i].parentNode.parentNode.style.display = "none"

    请看我在这里叉出的完整代码笔: https://codepen.io/anon/pen/gjKgjN

        4
  •  0
  •   Tschallacka    6 年前

    你在隐藏标题。你想隐藏的是卡片。

    您可以通过执行h5[i].parentNode.parentNode来执行此操作,因为标题嵌套在卡的两层深处。

    如果你的客户端浏览器支持它,你可以使用 Closest ancestor matching selector using native DOM?

    或者如果您可以使用jQuery搜索 $(h5[i]).closest('.card');

    function myFunction() {
        var input, filter, card, h5, a, i;
        input = document.getElementById("myFilter");
        filter = input.value.toUpperCase();
        card = document.getElementById("myItems");
        h5 = card.getElementsByTagName("h5");
        for (i = 0; i < h5.length; i++) {
            var current = h5[i];
            a = current.getElementsByTagName("a")[0];
            if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
                current.parentNode.parentNode.style.display = "";
            } else {
                current.parentNode.parentNode.style.display = "none";
            }
        }
    }
    .container {
      padding: 10px;
    }
    
    ul li {
      list-style: none;
      
    }
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <div class="container">
      <div class="row">
        <div class="col-sm-12 mb-3">
          <input type="text" id="myFilter" class="form-control" onkeyup="myFunction()" placeholder="Search for names..">
        </div>
      </div>
      <div class="row" id="myItems">
        <div class="col-sm-12 mb-3">
          <div class="card">
            <div class="card-body">
              <h5 class="card-title"><a href="#">Card One</a></h5>
              <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
              <p class="card-text">Some text.</p>
            </div>
          </div>
    
          <div class="card">
            <div class="card-body">
              <h5 class="card-title"><a href="#">Card Two</a></h5>
              <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
              <p class="card-text">Some text.</p>
            </div>
          </div>
    
          <div class="card">
            <div class="card-body">
              <h5 class="card-title"><a href="#">Card Three</a></h5>
              <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
              <p class="card-text">Some text.</p>
            </div>
          </div>      
        </div>    
      </div>
    </div>

    但我建议你用 getElementsByClassName 要获取所有的卡,然后遍历它们,根据类名选择h5元素,然后访问 innerText 在h5中,不可见的文本就像一个链接 title="some thing cool here" 不会碍事的。

    请参阅下面的片段。

    function myFunction() {
        var input, filter, myItems, cards, i, current, h5, text;
        input = document.getElementById("myFilter");
        filter = input.value.toUpperCase();
        myItems = document.getElementById("myItems");
        cards = myItems.getElementsByClassName("card");
        
        for (i = 0; i < cards.length; i++) {
            current = cards[i];
            h5 = current.getElementsByClassName('card-title')[0];
            text = h5.innerText.toUpperCase();
            if (text.indexOf(filter) > -1) {
                current.style.display = "";
            } else {
                current.style.display = "none";
            }
        }
    }
    .容器{
    衬垫:10px;
    }
    
    乌尔里{
    列表样式:无;
    
    }
    <link rel=“stylesheet”href=“https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.cssintegrity=“sha384-gn5384xqqqqaowxa+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXmcrossorigin=“anonymous”>
    <div class=“container”>
    <div class=“row”>
    <div class=“col-sm-12 mb-3”>
    <input type=“text”id=“myFilter”class=“form controlonkeyup=“myFunction()”placeholder=“搜索名称..”>
    </分区>
    </分区>
    <div class=“row”id=“myItems”>
    <div class=“col-sm-12 mb-3”>
    <div class=“card”>
    <div class=“card body”>
    <
    <h6 class=“card subtitle mb-2 text muted”>卡字幕<h6>
    <p class=“card text”>一些文本。<p>
    </分区>
    </分区>
    
    <div class=“card”>
    <div class=“card body”>
    <h5 class=“card title”><a href=“#”>第二张卡</a></h5>
    <h6 class=“card subtitle mb-2 text muted”>卡字幕<h6>
    <p class=“card text”>一些文本。<p>
    </分区>
    </分区>
    
    <div class=“card”>
    <div class=“card body”>
    <
    <h6 class=“card subtitle mb-2 text muted”>卡字幕<h6>
    <p class=“card text”>一些文本。<p>
    </分区>
    </分区>
    </分区>
    </分区>
    </分区>