如何使用简单的 javascript 过滤 html 表格?
Posted
技术标签:
【中文标题】如何使用简单的 javascript 过滤 html 表格?【英文标题】:How to filter a html table using simple javascript? 【发布时间】:2018-12-13 17:02:21 【问题描述】:我有一个过滤表格的代码。它将仅基于第一列进行过滤。如何让它单独过滤第二列。还有如何过滤完整的表?
我无法弄清楚执行此操作的方法。我试图在没有任何其他外部库的情况下获得帮助。
<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>
<script>
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";
</script>
JS Fiddle
【问题讨论】:
修改td = tr[i].getElementsByTagName("td")[0];
为td = tr[i].getElementsByTagName("td")[1];
?
那行得通...如果我需要从完整表中搜索怎么办?
两个 for 循环应该可以正常工作。
我为你添加了多列搜索。
【参考方案1】:
过滤所有Html表格:
const myFunction = () =>
const trs = document.querySelectorAll('#myTable tr:not(.header)')
const filter = document.querySelector('#myInput').value
const regex = new RegExp(filter, 'i')
const isFoundInTds = td => regex.test(td.innerHTML)
const isFound = childrenArr => childrenArr.some(isFoundInTds)
const setTrStyleDisplay = ( style, children ) =>
style.display = isFound([
...children // <-- All columns
]) ? '' : 'none'
trs.forEach(setTrStyleDisplay)
input#myInput width: 220px;
table#myTable width: 100%;
table#myTable th text-align: left; padding: 20px 0 10px;
<input
type="text"
id="myInput"
onkeyup="myFunction()"
placeholder="Search for names or countries.."
title="Type in a name or a country">
<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>
仅过滤特定的 Html 表格列
国家,在本例中是索引为 1 的列const myFunction = () =>
const columns = [
name: 'Name', index: 0, isFilter: false ,
name: 'Country', index: 1, isFilter: true
]
const filterColumns = columns.filter(c => c.isFilter).map(c => c.index)
const trs = document.querySelectorAll(`#myTable tr:not(.header)`)
const filter = document.querySelector('#myInput').value
const regex = new RegExp(escape(filter), 'i')
const isFoundInTds = td => regex.test(td.innerHTML)
const isFound = childrenArr => childrenArr.some(isFoundInTds)
const setTrStyleDisplay = ( style, children ) =>
style.display = isFound([
...filterColumns.map(c => children[c]) // <-- filter Columns
]) ? '' : 'none'
trs.forEach(setTrStyleDisplay)
input#myInput width: 220px;
table#myTable width: 100%;
table#myTable th text-align: left; padding: 20px 0 10px;
<input
type="text"
id="myInput"
onkeyup="myFunction()"
placeholder="Search for names or countries.."
title="Type in a name or a country">
<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>
【讨论】:
如果你想单独过滤每一列,而不是搜索整个表怎么办? @bartcubrich 我已经编辑了答案以添加对按n
列数过滤的支持
谢谢,这完全有效。但是,我注意到,如果您将表设置为仅显示几行,则只会过滤这些行。有什么简单的解决方法吗?我在桌子上使用这个: $(document).ready(function() $('#permits').DataTable( "pagingType": "full_numbers", "order": [[ 1, "asc" ]] ); );【参考方案2】:
你快到了。您需要做的就是创建另一个 for 循环并遍历行中的所有 td
元素,并使用它们进行过滤。这样,如果您以后添加任何列,过滤器将继续工作。
在下面的sn-p中,我已经做到了,并稍微修改了隐藏逻辑。我隐藏了所有开始的行,如果找到匹配项,我会取消隐藏它。
for (i = 1; i < tr.length; i++)
// Hide the row initially.
tr[i].style.display = "none";
td = tr[i].getElementsByTagName("td");
for (var j = 0; j < td.length; j++)
cell = tr[i].getElementsByTagName("td")[j];
if (cell)
if (cell.innerHTML.toUpperCase().indexOf(filter) > -1)
tr[i].style.display = "";
break;
function myFunction()
var input, filter, table, tr, td, cell, i, j;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 1; i < tr.length; i++)
// Hide the row initially.
tr[i].style.display = "none";
td = tr[i].getElementsByTagName("td");
for (var j = 0; j < td.length; j++)
cell = tr[i].getElementsByTagName("td")[j];
if (cell)
if (cell.innerHTML.toUpperCase().indexOf(filter) > -1)
tr[i].style.display = "";
break;
<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>
注意:我建议使用innerText
而不是innerHTML
进行过滤。如果单元格中有 HTML 内容,innerHTML
可能会干扰过滤。
【讨论】:
如何显示“未找到匹配项”而不是显示空表? @vigneshselvarathinam 创建一个变量来跟踪您显示的行数,最后,如果计数为零,您可以发出警报。 @Nisarg 我按照您的建议尝试了innerText
,它实际上比innerHTML
慢得多。您的代码又好又快。 (我过滤了大约 1000 行)。
@Andrew 是的,我相信在某些情况下 innerHTML 更快(尤其是 IE),但 innerText 仍然更可取,因为它不包含 HTML 标记。你甚至可以尝试使用 textContent 。
我没有测试任何性能,但是我声明了一个变量 visible = "none" 而不是 tr[i].style.display = "none";。然后,在检查了 innerText 之后,我设置了变量 visible = ""。在每次迭代结束时,我将行显示属性设置为等于可见变量。这样我就避免了两次设置相同的属性。【参考方案3】:
只改变
td = tr[i].getElementsByTagName("td")[0];
到
td = tr[i].getElementsByTagName("td")[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 (var i = 0; i < tr.length; i++)
var tds = tr[i].getElementsByTagName("td");
var flag = false;
for(var j = 0; j < tds.length; j++)
var td = tds[j];
if (td.innerHTML.toUpperCase().indexOf(filter) > -1)
flag = true;
if(flag)
tr[i].style.display = "";
else
tr[i].style.display = "none";
<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>
【讨论】:
【参考方案4】:有
td = tr[i].getElementsByTagName("td")[0];
您只选择了第一个td
。相反,请检查td
s 中的some
是否包含有问题的字符串:
function myFunction()
const input = document.getElementById("myInput");
const inputStr = input.value.toUpperCase();
document.querySelectorAll('#myTable tr:not(.header)').forEach((tr) =>
const anyMatch = [...tr.children]
.some(td => td.textContent.toUpperCase().includes(inputStr));
if (anyMatch) tr.style.removeProperty('display');
else tr.style.display = 'none';
);
<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>
【讨论】:
【参考方案5】:这里是创建一个 HTML 表格的代码,每个表格上都有一个过滤器选项。相信我,这很容易并且对我有用。试一试。我将其应用于我的 JSON 数据。
为此,我将此归功于https://www.jqueryscript.net/table/filter-each-column.html
function checkval()1==$("tbody tr:visible").length&&"No result found"==$("tbody tr:visible td").html()?$("#rowcount").html("0"):$("#rowcount").html($("tr:visible").length-1)$(document).ready(function()$("#rowcount").html($(".filterable tr").length-1),$(".filterable .btn-filter").click(function()var t=$(this).parents(".filterable"),e=t.find(".filters input"),l=t.find(".table tbody");1==e.prop("disabled")?(e.prop("disabled",!1),e.first().focus()):(e.val("").prop("disabled",!0),l.find(".no-result").remove(),l.find("tr").show()),$("#rowcount").html($(".filterable tr").length-1)),$(".filterable .filters input").keyup(function(t)if("9"!=(t.keyCode||t.which))var e=$(this),l=e.val().toLowerCase(),n=e.parents(".filterable"),i=n.find(".filters th").index(e.parents("th")),r=n.find(".table"),o=r.find("tbody tr"),d=o.filter(function()return-1===$(this).find("td").eq(i).text().toLowerCase().indexOf(l));r.find("tbody .no-result").remove(),o.show(),d.hide(),d.length===o.length&&r.find("tbody").prepend($('<tr class="no-result text-center"><td colspan="'+r.find(".filters th").length+'">No result found</td></tr>'))$("#rowcount").html($("tr:visible").length-1),checkval()));
.filterablemargin-top:15px.filterable .panel-heading .pull-rightmargin-top:-20px.filterable .filters input[disabled]background-color:transparent;border:none;cursor:auto;box-shadow:none;padding:0;height:auto.filterable .filters input[disabled]::-webkit-input-placeholdercolor:#333.filterable .filters input[disabled]::-moz-placeholdercolor:#333.filterable .filters input[disabled]:-ms-input-placeholdercolor:#333
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="panel panel-primary filterable">
<table class="table">
<thead>
<tr class="filters">
<th><input type="text" placeholder="#"></th>
<th><input type="text" placeholder="First Name"></th>
<th><input type="text" placeholder="Last Name"></th>
<th><input type="text" placeholder="Username"></th>
<th><input type="text" placeholder="PhoneNo"></th>
</tr>
</thead>
<tbody>
<tr>
<td>10</td>
<td>Tom</td>
<td>Amar</td>
<td>@TAmar</td>
<td>306-456-7890</td>
</tr>
<tr>
<td>20</td>
<td>Dick</td>
<td>Akbar</td>
<td>@DAkbar</td>
<td>456-456-7890</td>
</tr>
<tr>
<td>30</td>
<td>Harry</td>
<td>Anthony</td>
<td>@HAnthony</td>
<td>526-456-7890</td>
</tr>
</tbody>
</table>
<p>No.of Rows : <span id="rowcount"></span></p>
</div>
【讨论】:
【参考方案6】:如果你想单独对第二列进行过滤,那么下面对 Yosvel Quintero Arguelles 的代码进行一些修改
const table = document.getElementById("tableId");
const trs = table.querySelectorAll('tr:nth-child(n)');
// Or if you have headers, use line below instead of above
// const trs = document.querySelectorAll('#tableId tr:not(.header)');
const filter = document.querySelector('#myInput').value;
const regex = new RegExp(filter, 'i');
const isFoundInTds = (td) => regex.test(td.innerHTML);
const setTrStyleDisplay = ( style, children ) =>
// Here 1 represents second column
style.display = isFoundInTds(children[1]) ? '' : 'none';
;
trs.forEach(setTrStyleDisplay);
【讨论】:
【参考方案7】:你也可以这样用js过滤表格 添加一个正在处理点击的按钮
<button class="btn btn-secondary mx-2"
type="submit"
onclick="sortTableyear3()">3</button>
然后在你的 .js 文件或脚本标签中添加这个函数
function sortTableyear3()
var input, filter, table, tr, td, i, txtValue;
input = 3; // change this accordingly
filter = input.value;
table = document.getElementById("regstud-table");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++)
td = tr[i].getElementsByTagName("td")[2];// 2 is for 3rd column
if (td)
txtValue = td.textContent || td.innerText;
if (txtValue == input)
tr[i].style.display = "";
else
tr[i].style.display = "none";
这将仅显示第三列值为 3 的行。并且在表中使用大于和过滤器
【讨论】:
【参考方案8】:超级简单的解决方案。区分大小写。所有列。
红利:有debound功能
document.getElementById('filter').addEventListener('keyup', debound(filter_table, 500))
function filter_table(e)
const rows = document.querySelectorAll('tbody tr')
rows.forEach(row =>
row.style.display = (row.innerText.includes(e.target.value)) ? '' : 'none'
)
function debound(func, timeout)
let timer
return (...args) =>
if (!timer)
func.apply(this, args);
clearTimeout(timer)
timer = setTimeout(() =>
func.apply(this, args)
timer = undefined
, timeout)
<input type="text" id="filter">
<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>
【讨论】:
以上是关于如何使用简单的 javascript 过滤 html 表格?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 JavaScript 使每一列(独立地)可过滤 HTML?
过滤器的url-pattern设置了a.htm,访问a.htm,不走过滤器?
图书馆 - 添加书籍 - HTM、CSS、JavaScript