【问题标题】:Multi-Filterable Table with JS带有 JS 的多过滤表
【发布时间】:2015-07-28 09:54:04
【问题描述】:

我已经设法根据自己的喜好修改了一个可过滤的表格 JS 脚本,但我想通过使它更高级,以便我可以从剩余的过滤项目中过滤,但我不太确定如何去做吧。

这是一个jsfiddle,其设置与我所拥有的类似。自从我开始弄乱代码以来,代码变得更加混乱,您可能会看到我正在尝试使用表单来确保我们没有开始覆盖我们的 display:none's 但后来我意识到我有点过分了头。

为了澄清,我希望能够做的是过滤名称,然后进一步过滤剩余的列表,例如按类型。

有没有一种我完全想念的有效方法?

这是原始过滤器代码,在我弄乱它之前它更清晰:

function filter(term, _id, cellNr){
    var suche = term.value.toLowerCase();
    var table = document.getElementById(_id);
    var ele;
    for (var r = 2; r < table.rows.length; r++){
        ele = table.rows[r].cells[cellNr].innerHTML.replace(/<[^>]+>/g,"");
        if (ele.toLowerCase().indexOf(suche)>=0 )
            table.rows[r].style.display = '';
        else table.rows[r].style.display = 'none';
    }
}

【问题讨论】:

    标签: javascript jquery forms filter


    【解决方案1】:

    我自己会这样做:

        function filter(_id) {
            var table = document.getElementById(_id);
            //get all filters.
            var getFilters = [table.querySelectorAll("input")[0].value.toLowerCase(),
                          table.querySelectorAll("input")[1].value.toLowerCase(),
                          table.querySelectorAll("input")[2].value.toLowerCase()]
            
            for (var r = 2; r < table.rows.length; r++) 
            {
                //strip tags
                var el1 = table.rows[r].cells[0].innerHTML.replace(/<[^>]+>/g, "");
                var el2 = table.rows[r].cells[1].innerHTML.replace(/<[^>]+>/g, "");
                var el3 = table.rows[r].cells[2].innerHTML.replace(/<[^>]+>/g, "");
                
                var search1 = el1.toLowerCase().indexOf(getFilters[0]);
                var search2 = el2.toLowerCase().indexOf(getFilters[1]);
                var search3 = el3.toLowerCase().indexOf(getFilters[2]);
        
                //test all searches, if found or el = empty display
                if ( (search1 >= 0 || el1 == "" ) && (search2 >= 0 || el2 == "" )  && (search3 >= 0 || el3 == "" )) {
                    table.rows[r].style.display = '';
                } else {
                    table.rows[r].style.display = 'none';
                }
            }        
        }
        <table id="table">
      <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Type</th>
      </tr>
      <tr>
          <td><input placeholder="search" name="filterinput3" onkeyup="filter('table')" type="text" size="3"></input></td>
          <td><input placeholder="search" name="filterinput3" onkeyup="filter('table')" type="text" size="3"></input></td>
          <td><input placeholder="search" name="filterinput3" onkeyup="filter('table')" type="text" size="3"></input></td>
      </tr>
      <tr>
        <td>1</td>
        <td>Bulbasaur</td>
        <td>Grass</td>
      </tr>
      <tr>
        <td>4</td>
        <td>Charmander</td>
        <td>Fire</td>
      </tr>
      <tr>
        <td>7</td>
        <td>Squirtle</td>
        <td>Water</td>
      </tr>
        <tr>
        <td>1</td>
        <td>Bulbasaur</td>
        <td>Poison</td>
      </tr>
        <tr>
        <td>6</td>
        <td>Charizard</td>
        <td>Flying</td>
      </tr>
    </table>

    首先,从输入框中获取所有输入。将其存储在一个名为 getFilters 的数组中。

    然后:
    搜索不同的单元格,看看是否有匹配项。

    当存在匹配项(不是-1)或该列的输入为空时,返回 true。所有三个条件都需要返回 true 才能显示一行。如果不隐藏该行。

    所以id : 1 其他两个输入为空将只产生具有两种类型的bulbasaur。

    这里真正的诀窍是条件:

    (search1 &gt;= 0 || el1 == "" ) &amp;&amp; (search2 &gt;= 0 || el2 == "" )

    它们用括号分成块。将分别评估为真或假。本例中有三个这样的块。


    很久以前就已经回答了这个问题,值得采用更现代的方法:

    function filter(_id) {
      const table = document.getElementById(_id);
      //get all filters
      const getFilters = [...table.querySelectorAll("input")].map(element => element.value.toLowerCase());
     document.querySelectorAll("tr:nth-child(n+3) > td:first-child").forEach((firstTD) => {
        //iterate to the next to td's using nextSibling
        const textArray = [firstTD.textContent, firstTD.nextElementSibling.textContent, firstTD.nextElementSibling.nextElementSibling.textContent];
        const found = textArray.every((element, index) => {
          return element.toLowerCase().indexOf(getFilters[index]) >= 0 || getFilters[index] == "";
        });
    
        if (found) {
           firstTD.parentElement.style.display = '';
        } else {
          firstTD.parentElement.style.display = 'none';
        }
    
      });
    
    }
    <table id="table">
      <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Type</th>
      </tr>
      <tr>
        <td><input placeholder="search" name="filterinput3" onkeyup="filter('table')" type="text" size="3"></input>
        </td>
        <td><input placeholder="search" name="filterinput3" onkeyup="filter('table')" type="text" size="3"></input>
        </td>
        <td><input placeholder="search" name="filterinput3" onkeyup="filter('table')" type="text" size="3"></input>
        </td>
      </tr>
      <tr>
        <td>1</td>
        <td>Bulbasaur</td>
        <td>Grass</td>
      </tr>
      <tr>
        <td>4</td>
        <td>Charmander</td>
        <td>Fire</td>
      </tr>
      <tr>
        <td>7</td>
        <td>Squirtle</td>
        <td>Water</td>
      </tr>
      <tr>
        <td>1</td>
        <td>Bulbasaur</td>
        <td>Poison</td>
      </tr>
      <tr>
        <td>6</td>
        <td>Charizard</td>
        <td>Flying</td>
      </tr>
    </table>

    【讨论】:

    • 绝对是一种更简单的方法。我添加了几个 for 循环来处理更大的搜索列表,但我使用了你的代码,谢谢!
    • 不错。我也想到了循环。但为了展示基本概念,我认为写出三个搜索条件会更清晰。
    猜你喜欢
    • 2012-12-14
    • 2013-05-20
    • 2012-06-09
    • 2021-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-03
    • 1970-01-01
    相关资源
    最近更新 更多