首页 > 解决方案 > 按文本字段过滤列表

问题描述

我创建了一个小应用程序,可以帮助我提高工作效率。它通过文本内容过滤标签列表。它目前非常适合查找连续的文本行,但我更愿意将其重新实现为适用于非连续文本组合的过滤器。

例如,如果标签内的字符串是“Appleville, MN”,如果您输入“Apple”或“Appleville”或“App”,当前过滤器将找到它,但我希望能够通过输入成功过滤作为“应用程序 MN”。

谁能指出我正确的方向?我不确定我需要使用什么确切的算法。谢谢!

PS:我在下面包含了一些代码,其中包含我正在过滤的搜索项类型、当前过滤器功能以及搜索字段的示例。

function filterList() {
  var input, filter, ul, li, a, i, txtValue;
  input = document.getElementById('myInput');
  filter = input.value.toUpperCase();
  ul = document.getElementById("itemList");
  li = ul.getElementsByTagName('li');
  for (i = 0; i < li.length; i++) {
    a = li[i].getElementsByTagName("a")[0];
    txtValue = a.textContent || a.innerText;
    if (txtValue.toUpperCase().indexOf(filter) > -1) {
      li[i].style.display = "";
    } else {
      li[i].style.display = "none";
    }
  }
}
<input type="text" id="myInput" onkeyup="filterList()" placeholder="Search list..">
<ul id="itemList">
  <li onclick=applevilleMN()><a href="#">Appleville, MN</a></li>
  <li onclick=orangevilleOR()><a href="#">Orangeville, OR</a></li>
  <li onclick=kiwivilleCA()><a href="#">Kiwiville, CA</a></li>
  <li onclick=bananavilleCA()><a href="#">Bananaville, CA</a></li>
</ul>

标签: javascripthtmlfilter

解决方案


这是一个修改后的版本,可以做你想做的事。

它用空格分割过滤器字符串以创建过滤器数组,li仅当它们对数组的每个子字符串都有效时才显示。

function filterList() {
    var input, filter, ul, li, a, i, txtValue;
    input = document.getElementById('myInput');
    filter = input.value.toUpperCase();
    ul = document.getElementById("itemList");
    li = ul.getElementsByTagName('li');

    for (i = 0; i < li.length; i++) {
      a = li[i].getElementsByTagName("a")[0];
      txtValue = a.textContent || a.innerText;
      
      // split filter by spaces, gives ["app", "MN"] in your example  
      let filters = filter.split(" ") 

      // remove the empty filters (if your filter string 
      // starts or ends by a space) since they are source of errors

      // Array.filter takes in parameter a function returning a boolean
      // it create a new array containing only element where 
      // the function returned truthy value

      // here we return the length of the string which is falsy (== 0) for "" 
      // and truthy for every other string (!= 0)
      filters = filters.filter(f => f.length)   

      let shouldDisplay = true
      // test each filter and store true only if string contains all filter
      filters.forEach(filt => {
        shouldDisplay = shouldDisplay && txtValue.toUpperCase().includes(filt)
      })
      
      // update visibility
      // set visible if the string include all filters
      // or if there is no filter
      li[i].style.display = (shouldDisplay || filters.length === 0) ? "" : "none";
    }
  }
<ul id="itemList">
      <li onclick=applevilleMN()><a href="#" >Appleville, MN</a></li>
      <li onclick=orangevilleOR()><a href="#" >Orangeville, OR</a></li>
      <li onclick=kiwivilleCA()><a href="#" >Kiwiville, CA</a></li>
      <li onclick=bananavilleCA()><a href="#" >Bananaville, CA</a></li>
</ul>

<input type="text" id="myInput" onkeyup="filterList()" placeholder="Search list.." >

文档:Array.filter,,,truthy valuesfalsy values


推荐阅读