多列过滤表格

10

我在我的页面中使用了w3School的代码,它可以正常工作,但只能过滤一列,不知道如何创建循环,但希望有更简单的解决方案。

    td = tr[i].getElementsByTagName("td")[0];     

将这里的0改为1会更改该列,我试过很多不同的方法但都没有找到合适的,作为非程序员,我不知道是否有其他属性可以允许多列,我已经花费了很多时间搜索,请帮忙。

function myFunction() {
  var input, filter, table, tr, td, i;
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  table = document.getElementById("myTable");
  tr = table.getElementsByTagName("tr");
  for (i = 0; i < tr.length; i++) {
    td = tr[i].getElementsByTagName("td")[0];
    if (td) {
      if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
        tr[i].style.display = "";
      } else {
        tr[i].style.display = "none";
      }
    }
  }
}
* {
  box-sizing: border-box;
}

#myInput {
  background-image: url('/css/searchicon.png');
  background-position: 10px 10px;
  background-repeat: no-repeat;
  width: 100%;
  font-size: 16px;
  padding: 12px 20px 12px 40px;
  border: 1px solid #ddd;
  margin-bottom: 12px;
}

#myTable {
  border-collapse: collapse;
  width: 100%;
  border: 1px solid #ddd;
  font-size: 18px;
}

#myTable th,
#myTable td {
  text-align: left;
  padding: 12px;
}

#myTable tr {
  border-bottom: 1px solid #ddd;
}

#myTable tr.header,
#myTable tr:hover {
  background-color: #f1f1f1;
}
<h2>My Customers</h2>

<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search             for names.." title="Type in a name">

<table id="myTable">
  <tr class="header">
    <th style="width:60%;">Name</th>
    <th style="width:40%;">Country</th>
  </tr>
  <tr>
    <td>Alfreds Futterkiste</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Berglunds snabbkop</td>
    <td>Sweden</td>
  </tr>
  <tr>
    <td>Island Trading</td>
    <td>UK</td>
  </tr>
  <tr>
    <td>Koniglich Essen</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Laughing Bacchus Winecellars</td>
    <td>Canada</td>
  </tr>
  <tr>
    <td>Magazzini Alimentari Riuniti</td>
    <td>Italy</td>
  </tr>
  <tr>
    <td>North/South</td>
    <td>UK</td>
  </tr>
  <tr>
    <td>Paris specialites</td>
    <td>France</td>
  </tr>
</table>


1
请使用除w3schools之外的其他资源,因为它并不是特别好(例如MDN用于tablesrows)。您可以使用tr[i].cells[0]代替tr[i].getElementsByTagName("td")[0]。这样打字量会少很多。;-) 另外,请整齐地格式化您的代码,阅读起来越容易,人们就越有可能提供帮助。 - RobG
15个回答

44

在网上有更好的资源,比W3 Schools要好得多,我认为你真的应该避免访问那个网站。话虽如此,如果你想匹配整行,只需要查看tr而不是其中一个td

function myFunction() {
    var input = document.getElementById("myInput");
    var filter = input.value.toUpperCase();
    var table = document.getElementById("myTable");
    var tr = table.getElementsByTagName("tr");
    for (var i = 0; i < tr.length; i++) {
        if (tr[i].textContent.toUpperCase().indexOf(filter) > -1) {
            tr[i].style.display = "";
        } else {
            tr[i].style.display = "none";
        }      
    }
}

如果你想要过滤多个列而不是整行,只需在条件中使用 OR(||)即可:
function myFunction() {
    var input = document.getElementById("myInput");
    var filter = input.value.toUpperCase();
    var table = document.getElementById("myTable");
    var tr = table.getElementsByTagName("tr");
    var tds = tr.getElementsByTagName('td');
    
    for (var i = 0; i < tr.length; i++) {
        var firstCol = tds[0].textContent.toUpperCase();
        var secondCol = tds[1].textContent.toUpperCase();
        if (firstCol.indexOf(filter) > -1 || secondCol.indexOf(filter) > -1) {
            tr[i].style.display = "";
        } else {
            tr[i].style.display = "none";
        }      
    }
}

一些原因说明为什么这个教程不太好:你应该避免使用innerHTML,而应该使用textContent,因为你的单元格可能包含HTML代码,用户在搜索可见文本时可能会输入标签名称,并对匹配结果感到困惑。你应该给你的函数起一个能说明其功能的名字(例如,filterTable而不是myFunction)。此外,还有更简单的方法来访问表格数据(例如,tr.cells)。如果你给#myInput添加一个keyup事件监听器,那么每次调用函数时就不需要查找DOM节点了。以下是一个示例:

function filterTable(event) {
    var filter = event.target.value.toUpperCase();
    var rows = document.querySelector("#myTable tbody").rows;
    
    for (var i = 0; i < rows.length; i++) {
        var firstCol = rows[i].cells[0].textContent.toUpperCase();
        var secondCol = rows[i].cells[1].textContent.toUpperCase();
        if (firstCol.indexOf(filter) > -1 || secondCol.indexOf(filter) > -1) {
            rows[i].style.display = "";
        } else {
            rows[i].style.display = "none";
        }      
    }
}

document.querySelector('#myInput').addEventListener('keyup', filterTable, false);
<input id="myInput" type="text" />
<table id="myTable">
 <thead>
  <tr class="header">
    <th style="width:60%;">Name</th>
    <th style="width:40%;">Country</th>
  </tr>
 </thead>
 <tbody>
  <tr>
    <td>Alfreds Futterkiste</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Berglunds snabbkop</td>
    <td>Sweden</td>
  </tr>
  <tr>
    <td>Island Trading</td>
    <td>UK</td>
  </tr>
  <tr>
    <td>Koniglich Essen</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Laughing Bacchus Winecellars</td>
    <td>Canada</td>
  </tr>
  <tr>
    <td>Magazzini Alimentari Riuniti</td>
    <td>Italy</td>
  </tr>
  <tr>
    <td>North/South</td>
    <td>UK</td>
  </tr>
  <tr>
    <td>Paris specialites</td>
    <td>France</td>
  </tr>
 </tbody>
</table>


3
"Rob你太棒了!我花了一些时间才明白你做了什么,但现在它开始运作了,非常感谢(上一个有效)。" - Rolandas Vizbara
1
这个很好地解决了问题。请问如何包含两个不同的输入?谢谢! - joshlsullivan
1
嗨@joshlsullivan,您是在询问如何让两个不同的文本输入过滤表格吗? - Rob M.
1
@RobM。是的,先生。 - joshlsullivan
2
@joshlsullivan 如果你想让它们执行相同的过滤操作,你可以使用 querySelectorAll 和多个选择器,并使用 forEach 附加事件监听器。示例:https://jsbin.com/meyugud/edit?html,js,output - Rob M.
显示剩余8条评论

3

添加 || 并在 if 语句下添加新条件完全奏效了。

function myFunction() {
var input, filter, table, tr, td, i;
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  table = document.getElementById("myTable");
  tr = table.getElementsByTagName("tr");
  for (i = 0; i < tr.length; i++) {
    td = tr[i].getElementsByTagName("td")[0]; // for column one
     td1 = tr[i].getElementsByTagName("td")[1]; // for column two
/* ADD columns here that you want you to filter to be used on */
    if (td) {
      if ( (td.innerHTML.toUpperCase().indexOf(filter) > -1) || (td1.innerHTML.toUpperCase().indexOf(filter) > -1) )  {            
        tr[i].style.display = "";
      } else {
        tr[i].style.display = "none";
      }
    }
  }
} 
* {
  box-sizing: border-box;
}

#myInput {
  background-image: url('/css/searchicon.png');
  background-position: 10px 10px;
  background-repeat: no-repeat;
  width: 100%;
  font-size: 16px;
  padding: 12px 20px 12px 40px;
  border: 1px solid #ddd;
  margin-bottom: 12px;
}

#myTable {
  border-collapse: collapse;
  width: 100%;
  border: 1px solid #ddd;
  font-size: 18px;
}

#myTable th,
#myTable td {
  text-align: left;
  padding: 12px;
}

#myTable tr {
  border-bottom: 1px solid #ddd;
}

#myTable tr.header,
#myTable tr:hover {
  background-color: #f1f1f1;
}
<h2>My Customers</h2>

<input type="text" id="myInput" onkeyup="myFunction()" 
placeholder="Search for names.." title="Type in a name">

<table id="myTable">
  <tr class="header">
    <th style="width:60%;">Name</th>
    <th style="width:40%;">Country</th>
  </tr>
  <tr>
    <td>Alfreds Futterkiste</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Berglunds snabbkop</td>
    <td>Sweden</td>
  </tr>
  <tr>
    <td>Island Trading</td>
    <td>UK</td>
  </tr>
  <tr>
    <td>Koniglich Essen</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Laughing Bacchus Winecellars</td>
    <td>Canada</td>
  </tr>
  <tr>
    <td>Magazzini Alimentari Riuniti</td>
    <td>Italy</td>
  </tr>
  <tr>
    <td>North/South</td>
    <td>UK</td>
  </tr>
  <tr>
    <td>Paris specialites</td>
    <td>France</td>
  </tr>
</table>


1
将以下JQuery代码添加到文件的head标签中。#myinput 是搜索框的id,它是一个文本输入框。 #tab-id 是tbody的id,因此您应该明确地将表格分为thead和tbody部分。
<script>
    $(document).ready(function(){
        $("#myInput").on("keyup", function() {
            var value = $(this).val().toLowerCase();
            $("#tab-id tr").filter(function() {
                $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1);
            });
        });
    });
</script>

1
这是正确的函数。
function myFunction() {
    var input = document.getElementById("myInput");
    var filter = input.value.toUpperCase();
    var table = document.getElementById("myTable");
    var tr = table.getElementsByTagName("tr");
    for (var i = 0; i < tr.length; i++) {
        if (tr[i].textContent.toUpperCase().indexOf(filter) > -1) {
            tr[i].style.display = "";
        } else {
            tr[i].style.display = "none";
        }      
    }
}

应该是tr[i].textContent

1
你的代码很好。要添加多个列,您需要在if子句中添加||条件。
Rob的答案存在问题,如果使用tr,它将过滤掉表头。
以下是代码扩展:
function myFunction() {
var input, filter, table, tr, td, i;
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  table = document.getElementById("myTable");
  tr = table.getElementsByTagName("tr");
  for (i = 0; i < tr.length; i++) {
    td = tr[i].getElementsByTagName("td")[0]; // for column one
     td1 = tr[i].getElementsByTagName("td")[1]; // for column two
/* ADD columns here that you want you to filter to be used on */
    if (td) {
      if ( (td.innerHTML.toUpperCase().indexOf(filter) > -1) || (td1.innerHTML.toUpperCase().indexOf(filter) > -1) )  {            
        tr[i].style.display = "";
      } else {
        tr[i].style.display = "none";
      }
    }
  }
} 

1

您只需要添加另一个循环来遍历单元格,如下:

table = document.getElementById("myTable");
//  tr = table.getElementsByTagName("tr");
// Easier to use the rows collection:
var tr = table.rows;

for (i = 0; i < tr.length; i++) {

  // Easier to use the cells collection
  // td = tr[i].getElementsByTagName("td")[0];
  cells = row.cells;

  // Loop over all the cells
  for (var j=0, jLen=cells.length; j<jLen; j++) {
    td = cells[j];

    // Existing loop
    if (td) {
      if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
        tr[i].style.display = "";
      } else {
        tr[i].style.display = "none";
      }
    }
  }
}

难道直接使用整行的 innerHTML,然后循环遍历每个单元格不是更合理吗? - Rob M.
@RobM。—当然,或者textContent,但我认为循环遍历单元格提供了更好的学习机会。;-) - RobG

0

这个解决方案适用于具有多个值的多列过滤器

空文本框是用来输入筛选值的

所有文本框的类名都为'.filter_rep'

  $(document).on('keyup','.filter_rep',function () {
    var $this = $(this).val();
    var val_array = [];
    var id_array = [];

    $('.filter_rep').each(function () {
        thisval = $(this).val();
        id = '.'+$(this).attr('id');
        if (thisval){
            id_array.push(id);
            val_array.push(thisval);
        }
    });
    // using val_array to check all the columns and hide
    if(val_array.length > 0){
        $('tr').each(function () {
            $(this).show();
        });
        for (i=0;i<val_array.length;i++){
            $(id_array[i]).each(function () {
                if (!($(this).text().toLowerCase().indexOf(val_array[i]) > -1)){
                    $(this).parent().hide();
                }
            });
        }
    }else{
        $('tr').each(function () {
          $(this).show();
        });
    }
})

});

如果有任何疑问,请联系我!


0

我正在处理一个包含大量列表的项目,数据表格行通常超过1000-2000。最大的问题是在筛选大表格时出现的延迟,因为JS需要每次按键时检查整个HTML。

enter image description here

我测试了很多种方式,最快的方法是使用数组将数据聚集到一个地方,然后从数组中过滤它们,结果键将被发送回HTML以添加'collapse'类。

JAVASCRIPT

<script>
function multifilter_table(f_table, f_input, f_type, f_td) {
    const filter = {};
    f_input.forEach(function(currentValue, index, arr) {
        var in_val = (f_type[index] == 'i') ? document.getElementById(currentValue).value : document.getElementById(currentValue).options[document.getElementById(currentValue).selectedIndex].value;
        if (in_val != '')
            filter[index] = in_val;
    });

    var table = Array.prototype.map.call(trList = document.getElementById(f_table).getElementsByTagName('tr'), function(tr){
        return Array.prototype.map.call(tr.getElementsByTagName('td'), function(td){
            return td.textContent || td.innerText;
        });
    });
    
    for (i = 1; i < table.length; i++) {
        var match_input = true;
        for (let index in filter) {
            if (table[i][f_td[index]].indexOf(filter[index]) == -1)
                match_input = false;
        }
        match_input ? trList[i].classList.remove('collapse') : trList[i].classList.add('collapse');
    }
}
</script>

HTML + CSS

<style>
  .collapse {display: none;}
</style>


<table id="filter_table">
      <thead>
      <tr>
        <th><input id="filter_fname" onkeyup="TestFilter()" /></th>
        <th><input id="filter_lname" onkeyup="TestFilter()" /></th>
        <th><input id="filter_gender" onkeyup="TestFilter()" /></th>
        <th><input id="filter_depart" onkeyup="TestFilter()" /></th>
      </tr>
      </thead>
      <tbody>
      <tr>
        <td>John</td>
        <td>Doe</td>
        <td>Male</td>
        <td>Sales</td>
      </tr>
      <tr>
        <td>Mary</td>
        <td>Moe</td>
        <td>Female</td>
        <td>Service</td>
      </tr>
      <tr>
        <td>July</td>
        <td>Dooley</td>
        <td>Female</td>
        <td>Service</td>
      </tr>
      <tr>
        <td>Anja</td>
        <td>Ravendale</td>
        <td>Female</td>
        <td>Engineering</td>
      </tr>
      <tr>
        <td>Thomas</td>
        <td>Dubois</td>
        <td>Male</td>
        <td>Sales</td>
      </tr>
      <tr>
        <td>Deidre</td>
        <td>Masters</td>
        <td>Female</td>
        <td>Sales</td>
      </tr>
      <tr>
        <td>Sean</td>
        <td>Franken</td>
        <td>Male</td>
        <td>Engineering</td>
      </tr>
      </tbody>
    </table>

TestFilter() 函数的定义如下:

<script>
function TestFilter() {
    multifilter_table(  'filter_table',
                        ['filter_fname', 'filter_lname', 'filter_gender', 'filter_depart'],
                        ['i', 'i', 'i', 'i'],
                        ['0', '1', '2', '3']
                    );
}
</script>

0

基于你可能遵循的相同教程,接受三个不同的文本输入并相应地对行中的所有 's 进行排序:

function SortByMultiple() {

    //Declare needed variables
    var dateInput, nameInput, locationInput, dateFilter, nameFilter, locationFilter, table, tr, tdN, tdD, tdL, i;

    //Set inputs by getElementById
    nameInput = document.getElementById('nameInput');
    dateInput = document.getElementById('dateInput');
    locationInput = document.getElementById('locationInput');
    //Set filters
    nameFilter = nameInput.value.toUpperCase();
    dateFilter = dateInput.value.toUpperCase();
    locationFilter = locationInput.value.toUpperCase();
    //Set the table and tr variables
    table = document.getElementById("UL");
    tr = document.getElementsByTagName("tr");

    //Loop through items and hide those that don't match the query -->
    for (i = 0; i < tr.length; i++) {

        //Name is at index 0
        tdN = tr[i].getElementsByTagName("td")[0];
        //Date is at index 2
        tdD = tr[i].getElementsByTagName("td")[2];
        //Location is at index 1
        tdL = tr[i].getElementsByTagName("td")[1];

        if (tdN.innerHTML.toUpperCase().indexOf(nameFilter) > -1 && tdD.innerHTML.toUpperCase().indexOf(dateFilter) > -1 && tdL.innerHTML.toUpperCase().indexOf(locationFilter) > -1) {
            tr[i].style.display = "";
        }
        else {
            tr[i].style.display = "none";
        }
    }

}

通过使用AND将条件设置在一起,它们将全部被纳入筛选中考虑!


0

我在这里上传了代码,用于在两列之间搜索表格数据

function searching() {
    var input, filter, table, tr, td1, td2, i, txtValue;
    input = document.getElementById("search");
    filter = input.value.toUpperCase();
    table = document.getElementById("table");
    tr = table.getElementsByTagName("tr");

    for (i = 0; i < tr.length; i++) { 
        td1 = tr[i].getElementsByTagName("td")[0];
        td2 = tr[i].getElementsByTagName("td")[1];
        if (td1 || td2) {
            txtValue1 = td1.textContent || td1.innerText;
            txtValue2 = td2.textContent || td2.innerText;
            if (txtValue1.toUpperCase().indexOf(filter) > -1 || (txtValue2.toUpperCase().indexOf(filter) > -1)) {
                tr[i].style.display = "";
            } else {
                tr[i].style.display = "none";
            }
        }
    }
}


<input class="form-control my-3" id="search" onkeyup="searching()" type="search" placeholder="Search To-Do items here..." aria-label="Search">


<table class="table my-5">
    <thead class="thead-dark">
        <tr>
            <th scope="col ">Sr No.</th>
            <th scope="col ">Item</th>
            <th scope="col ">Description</th>
            <th scope="col ">Manage</th>
        </tr>
    </thead>
    <tbody id="table">
    </tbody>
</table>


1
虽然代码可能解决了问题,但一些解释会帮助未来的读者。请参考[答案]以改进您的帖子。 - Simon.S.A.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接