javascript - 通过 5 个单独的输入块过滤表
问题描述
我一直在尝试用 javascript 编写一个函数,这样我就可以通过 5 个单独的输入框过滤一个表格,一个用于表格的每个参数。W3schools 有一个解决方案,但它只覆盖了一列;我在这里找到了一堆关于“如何通过多个输入框过滤表格”的其他答案,但它们要么不起作用,要么另一个框会覆盖过滤过程,例如,如果我写了“x ” 在框一和框二中的“y”,表格必须包含td
列中包含的每个“y”,即使是没有“x”的那些。有什么解决办法吗?(第六栏没什么可补充的,就是这样)
html
<input type="text" id="inid" onkeyup="search()" placeholder="ID">
<input type="text" id="inplat" onkeyup="search()" placeholder="Platform">
<input type="text" id="inloc" onkeyup="search()" placeholder="Location">
<input type="text" id="incount" onkeyup="search()" placeholder="T-Count">
<input type="text" id="inauthor" onkeyup="search()" placeholder="Author">
<div id="table_div">
<table id="myTable">
<tr class="header">
<th>ID</th>
<th>Platform</th>
<th>Location</th>
<th>T-Count</th>
<th>Author</th>
<th></th>
</tr>
<tr>
<td>2-12-8374857-232</td>
<td>PC</td>
<td>Chongqing</td>
<td>4</td>
<td>Urben</td>
<td>More Info</td>
</tr>
<tr>
<td>3-23-3939473-324</td>
<td>PS</td>
<td>Dubai</td>
<td>3</td>
<td>Hichkas</td>
<td>More Info</td>
</tr>
<tr>
<td>3-43-3245235-432</td>
<td>Xbox</td>
<td>Paris</td>
<td>2</td>
<td>TheChicken</td>
<td>More Info</td>
</tr>
<tr>
<td>1-24-2594549-124</td>
<td>Stadia</td>
<td>Berlin</td>
<td>5</td>
<td>Scat1620</td>
<td>More Info</td>
</tr>
</table>
</div>
解决方案
这是我给你的建议
它使用了一些增强的 JS 技巧
// do everything inside a block to not conflict with global namespace
{
"use strict";
// define some magic values
const formSelector = '[data-filter-table-target]'
const columnSelector = '[data-column]'
const rowSelector = ':scope > tbody > tr';
const filteredClassName = 'filtered';
// define small Helper function that do exactly one thing
// returns an HTML element that matches the selector from the data-filter-table-target argument
const getTarget = form => document.querySelector(form.dataset.filterTableTarget)
// get all the first class rows (i.e. not nested inside a table) from this table's body
const getRows = table => Array.from(table.querySelectorAll(rowSelector))
// get the values from this form's inputs, which have a data-column argument
const getFilterValues = form => Array.from(form.querySelectorAll(columnSelector)).map(inp => ({'column': inp.dataset.column, 'value': inp.value}));
// check, if this cells text contains the value
const checkCellValue = (cell, value) => (new RegExp(value, 'i')).test(cell.textContent)
// get a table row's cell which data-column argument value matches the value argument
const getCell = (row, value) => row.querySelector(`[data-column="${value.column}"`)
// filter a row, if it does not match the value
const filterRow = (row, values) => {
const filtered = values.reduce((carry, value) => {
if (! checkCellValue(getCell(row, value), value.value)) { return true;}
return carry
}, false)
if (filtered) {
row.classList.add(filteredClassName)
} else {
row.classList.remove(filteredClassName)
}
}
// check all rows, if they should be filtered
const filterRows = (rows, values) => {
rows.forEach(row => filterRow(row, values))
}
// bahaviour on input
const onInput = e => {
// check, if input is called from inside a form which serves as filter
const form = e.target.closest(formSelector)
// otherwise return
if (!form) {return;}
const target = getTarget(form)
const rows = getRows(target)
const values = getFilterValues(form)
filterRows(rows, values)
}
// check for the global input event
document.addEventListener('input', onInput)
}
.filtered {
display: none;
}
<!-- the data-filter-table-target argument points to the table to be filtered -->
<form data-filter-table-target="#myTable">
<!-- the data-column arguments point to the table cells with the same argument -->
<input type="text" id="inid" placeholder="ID" data-column="ID">
<input type="text" id="inplat" placeholder="Platform" data-column="Platform">
<input type="text" id="inloc" placeholder="Location" data-column="Location">
<input type="text" id="incount" placeholder="T-Count" data-column="TCount">
<input type="text" id="inauthor" placeholder="Author" data-column="Author">
</form>
<div id="table_div">
<table id="myTable">
<thead>
<tr>
<th>ID</th>
<th>Platform</th>
<th>Location</th>
<th>T-Count</th>
<th>Author</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td data-column="ID">2-12-8374857-232</td>
<td data-column="Platform">PC</td>
<td data-column="Location">Chongqing</td>
<td data-column="TCount">4</td>
<td data-column="Author">Urben</td>
<td>More Info</td>
</tr>
<tr>
<td data-column="ID">3-23-3939473-324</td>
<td data-column="Platform">PS</td>
<td data-column="Location">Dubai</td>
<td data-column="TCount">3</td>
<td data-column="Author">Hichkas</td>
<td>More Info</td>
</tr>
<tr>
<td data-column="ID">3-43-3245235-432</td>
<td data-column="Platform">Xbox</td>
<td data-column="Location">Paris</td>
<td data-column="TCount">2</td>
<td data-column="Author">TheChicken</td>
<td>More Info</td>
</tr>
<tr>
<td data-column="ID">1-24-2594549-124</td>
<td data-column="Platform">Stadia</td>
<td data-column="Location">Berlin</td>
<td data-column="TCount">5</td>
<td data-column="Author">Scat1620</td>
<td>More Info</td>
</tr>
</tbody>
</table>
</div>
推荐阅读
- excel - Delphi 导出到 Excel - IDE 中编译代码的错误错误
- node.js - 编译 ejs 时 {FILE} 中出现意外的令牌“/”
- reactjs - useEffect 只有一个依赖项/React Hook useEffect 缺少依赖项:'props'
- python - 尝试使用 selenium webdriver 提取数据时出现问题
- node.js - 在本地主机上设置 cookie
- spring-boot - Thymeleaf 选择下拉列表未填充
- python - 如何在 Python 中对列表进行子串化
- r - 从 R 中的表中查找随时间的变化 - 将模型拟合到数据
- python - App Engine 标准 Python 3 环境变量未定义
- armeria - Armeria HTTP 客户端 - 如何添加查询字符串参数