我有一个 HTML 代码,我希望
filterTable()
函数在 searchInput 中输入内容后过滤 myTable 表。
例如,如果我输入“Rafael”,相关行应完全显示及其所有合并的单元格,而其余不包含该单词的行应隐藏。
我的代码:
function filterTable() {
var input = document.getElementById("searchInput");
var filter = input.value;
var table = document.getElementById("myTable");
var rows = table.getElementsByTagName("tr");
for (var i = 1; i < rows.length; i++) {
rows[i].style.display = "none";
}
for (var i = 1; i < rows.length; i++) {
var row = rows[i];
var cells = row.getElementsByTagName("td");
var rowMatchesFilter = false;
for (var j = 0; j < cells.length; j++) {
var cell = cells[j];
var cellContent = cell.textContent;
if (cellContent.indexOf(filter) > -1) {
rowMatchesFilter = true;
if (cell.getAttribute("rowspan")) {
var rowspan = parseInt(cell.getAttribute("rowspan"));
for (var k = 0; k < rowspan; k++) {
rows[i + k].style.display = "";
}
} else {
row.style.display = "";
}
break;
}
}
if (rowMatchesFilter) {
row.style.display = "";
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Table Search</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
padding: 8px;
width: 500px;
}
</style>
</head>
<body>
<h2>Information Table</h2>
<input type="text" id="searchInput" placeholder="Enter search text" oninput="filterTable()">
<table id="myTable">
<thead>
<tr>
<th>Building</th>
<th>Floor</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="5">Building 1</td>
<td rowspan="2">Floor 1</td>
<td>Martin</td>
</tr>
<tr>
<td>Cristiano</td>
</tr>
<tr>
<td rowspan="3">Floor 2</td>
<td>Karim</td>
</tr>
<tr>
<td>Rafael</td>
</tr>
<tr>
<td>Anna</td>
</tr>
<tr>
<td>Building 2</td>
<td>Floor 1</td>
<td>Carlos</td>
</tr>
</tbody>
</table>
</body>
</html>
但是,当我输入“Rafael”时,它会过滤,但显示:
建筑 | 地板 | 姓名 |
---|---|---|
拉斐尔 |
但我想表明:
建筑 | 地板 | 姓名 |
---|---|---|
1号楼 | 2楼 | 拉斐尔 |
我会使用不同的策略,通过使用碰撞检测:)
Set()
或 TD 元素// DOM utility functions:
const el = (sel, par = document) => par.querySelector(sel);
const els = (sel, par = document) => par.querySelectorAll(sel);
// Utils
const regEsc = (v) => v.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
const collides = (a, b) => a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y;
// Task: Filter table
const elSearch = el("#searchInput");
const elTbody = el("#myTable");
const filterTable = (value) => {
const val = elSearch.value.trim();
const elsTd = els("td", elTbody);
const reg = new RegExp(regEsc(val), "i");
const matchTd = [...elsTd].filter(elTd => reg.test(elTd.textContent));
const areas = matchTd.map((elTd) => {
const elTr = elTd.closest("tr");
const trBCR = elTr.getBoundingClientRect();
const tdBCR = elTd.getBoundingClientRect();
return {
x: trBCR.x,
y: tdBCR.y,
width: trBCR.width,
height: tdBCR.height,
}
});
const filteredTds = areas.reduce((acc, area) => {
elsTd.forEach((elTd) => collides(area, elTd.getBoundingClientRect()) && acc.add(elTd));
return acc;
}, new Set());
elsTd.forEach(elTd => {
elTd.classList.toggle("hidden", val.length && !filteredTds.has(elTd));
});
};
elSearch.addEventListener("input", filterTable);
table {
inline-size: 100%;
border-collapse: collapse;
th,
td {
border: 1px solid black;
.hidden {
display: none;
}
}
}
<input type="text" id="searchInput" autocomplete=off placeholder="Search...">
<table id="myTable">
<thead>
<tr><th>Building</th><th>Floor</th><th>Name</th></tr>
</thead>
<tbody>
<tr><td rowspan="5">Building 1</td><td rowspan="2">Floor 1</td><td>Martin</td></tr>
<tr><td>Cristiano</td></tr>
<tr><td rowspan="3">Floor 2</td><td>Karim</td></tr>
<tr><td>Rafael</td></tr>
<tr><td>Anna</td></tr>
<tr><td>Building 2</td><td>Floor 1</td><td>Carlos</td></tr>
</table>