带rowspan/colspan合并单元格的表格过滤功能异常修复求助
问题:带合并单元格的表格过滤功能异常
我编写了一段HTML代码,期望通过filterTable()函数在输入框输入内容后对myTable表格执行过滤操作。例如输入“Rafael”时,需完整显示包含该关键词的行及其对应的所有合并单元格,隐藏其余不匹配的行。
原JavaScript代码
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 = ""; } } }
原HTML代码
<!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”后,过滤结果显示异常,仅展示:
Building Floor Name Rafael
预期效果
输入“Rafael”后,应完整显示对应行及合并单元格:
Building Floor Name Building 1 Floor 2 Rafael
修复方案
问题根源在于原逻辑只处理了当前匹配行的向下合并单元格,未处理向上的合并单元格(即当前行之前的单元格通过rowspan覆盖到当前行的情况),导致合并的表头内容无法显示。修复后的函数会同时追溯上下关联的合并单元格,确保布局完整。
修复后的filterTable()函数:
function filterTable() { const input = document.getElementById("searchInput"); const filter = input.value.trim().toLowerCase(); const table = document.getElementById("myTable"); const rows = table.querySelectorAll("tbody tr"); // 先隐藏所有行 rows.forEach(row => row.style.display = "none"); if (!filter) { // 输入为空时恢复显示所有行 rows.forEach(row => row.style.display = ""); return; } // 遍历所有行查找匹配项 rows.forEach((row, rowIndex) => { const cells = row.querySelectorAll("td"); let isMatch = false; // 检查当前行是否包含匹配内容 cells.forEach(cell => { if (cell.textContent.trim().toLowerCase().includes(filter)) { isMatch = true; } }); if (isMatch) { // 显示当前匹配行 row.style.display = ""; // 向上追溯:查找覆盖当前行的合并单元格所在行 for (let i = 0; i < rowIndex; i++) { const prevRow = rows[i]; prevRow.querySelectorAll("td").forEach(cell => { const rowspan = parseInt(cell.getAttribute("rowspan")) || 1; // 若之前的单元格rowspan覆盖到当前行,则显示该行 if (i + rowspan > rowIndex) { prevRow.style.display = ""; } }); } // 向下处理:显示当前单元格rowspan覆盖的后续行 cells.forEach(cell => { const rowspan = parseInt(cell.getAttribute("rowspan")) || 1; if (rowspan > 1) { for (let k = 1; k < rowspan; k++) { rows[rowIndex + k]?.style.display = ""; } } }); } }); }
修复说明
- 大小写兼容:将输入和单元格内容统一转为小写,实现不区分大小写的搜索,提升用户体验。
- 向上追溯合并单元格:找到匹配行后,遍历之前的所有行,检查是否有单元格通过
rowspan覆盖当前行,确保合并的表头内容(如Building 1、Floor 2)能正常显示。 - 向下处理合并单元格:保留原逻辑中处理当前行单元格向下覆盖行的逻辑,确保合并单元格的所有关联行都被正确显示。
- 空输入处理:输入为空时直接恢复显示所有行,回到初始状态。
内容的提问来源于stack exchange,提问作者Mohammad Saeidi
相关产品推荐
相关产品推荐

