У меня есть таблица HTML, в которой используется атрибут rowspan. Я добавил в таблицу функцию поиска, но когда я ищу что-то вроде «Вашингтон», она удаляет значения «Обезьяна» и «Лев» из столбца ABC и заменяет их значениями из столбца DEF. Я не уверен, как это исправить. Есть ли у вас какие-либо рекомендации? Вот мой код -
function searchTable() {
var input, filter, table, tr, td, i, j, txtValue, match;
input = document.getElementById("searchInput");
filter = input.value.toUpperCase();
table = document.getElementById("example_full");
tr = table.getElementsByTagName("tr");
match = false;
for (i = 1; i < tr.length; i++) { // Skip the header row
tr[i].style.display = "none"; // Hide all rows initially
td = tr[i].getElementsByTagName("td");
for (j = 0; j < td.length; j++) {
if (td[j]) {
txtValue = td[j].textContent || td[j].innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
match = true;
break;
}
}
}
}
// Show or hide the no match message
document.getElementById("noMatch").style.display = match ? "none" : "block";
}
.no-match {
display : none;
color : red;
}
th {
border-left : 1px solid #dddddd;
border-top : 1px solid #dddddd;
border-bottom : 1px solid #dddddd;
border-right : 1px solid #dddddd;
background-color: darkgray;
}
<input type = "text" id = "searchInput" placeholder = "Search for records..." onkeyup = "searchTable()" />
<p id = "noMatch" class = "no-match">No matching records found</p>
<table id = "example_full">
<thead>
<tr>
<th>ABC</th>
<th>DEF</th>
<th>GHI</th>
<th>XXX</th>
<th>MMM</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan = "4" style = " vertical-align: middle;">MONKEY</td>
<td>AD123</td>
<td>434SDD</td>
<td>DFDDFF</td>
<td>FDFFD</td>
</tr>
<tr>
<td>LEMON</td>
<td> </td>
<td>FDFGGF</td>
<td>DFFDF</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td>FDDFF</td>
<td>Edison</td>
</tr>
<tr>
<td>FDDFFDF</td>
<td> </td>
<td>East</td>
<td>Washington</td>
</tr>
<tr>
<td rowspan = "3" style = " background-color: #F9F9F9; vertical-align: middle;">LION</td>
<td>GFFG</td>
<td>FGFGG</td>
<td>FGFG</td>
<td>FGGFGFG</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td>FGHGH</td>
<td>DDDFF</td>
</tr>
<tr>
<td></td>
<td>test2</td>
<td>FFGGFH</td>
<td>Washington</td>
</tr>
</tbody>
</table>
Вам нужно использовать диапазон строк? Что, если вы просто повторите значение «Обезьяна» для первых 4 строк и значение «Лев» для последних 3 строк. Если вы это сделаете, ваш код поиска и отображение будут работать правильно. @mplungjan прав, иначе становится довольно сложно управлять, когда <td> необходимо добавлять и удалять во время поиска.
Мы только что дали вам отличный способ. Итак, теперь вы хотите показать весь набор строк, если текст найден в ячейках, являющихся частью диапазона строк? Таким образом, каждая строка, в которой есть ячейка с текстом фильтра, должна знать, что она является частью диапазона строк, и также показывать строку, содержащую этот диапазон строк?
Убедитесь, что в каждой строке по 5 ячеек. В вашем случае вы сворачиваете до 4 ячеек в строках, которые не имеют диапазона строк.
Вот более упрощенная версия, использующая предложение imhvost, чтобы свернуть видимость вместо отображения: нет/скрытый
const input = document.getElementById("searchInput");
const noMatch = document.getElementById("noMatch");
const rows = document.querySelectorAll("#example_full tbody tr");
const searchTable = () => {
let filter = input.value.toUpperCase(),
match = false;
rows.forEach(row => {
let found = filter && Array.from(row.querySelectorAll('td')).some(td => td.textContent.toUpperCase().includes(filter));
row.style.visibility = filter && !found ? 'collapse' : 'visible';
if (found) match = true; // set if any hit
});
// Show or hide the no match message
noMatch.hidden = !filter || (filter && match);
}
input.addEventListener('input',searchTable);
.no-match {
color: red;
}
th {
border-left: 1px solid #dddddd;
border-top: 1px solid #dddddd;
border-bottom: 1px solid #dddddd;
border-right: 1px solid #dddddd;
background-color: darkgray;
}
<input type = "text" id = "searchInput" placeholder = "Search for records..." />
<p id = "noMatch" hidden class = "no-match">No matching records found</p>
<table id = "example_full">
<thead>
<tr>
<th>ABC</th>
<th>DEF</th>
<th>GHI</th>
<th>XXX</th>
<th>MMM</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan = "4" style = " vertical-align: middle;">MONKEY</td>
<td>AD123</td>
<td>434SDD</td>
<td>DFDDFF</td>
<td>FDFFD</td>
</tr>
<tr>
<td>LEMON</td>
<td> </td>
<td>FDFGGF</td>
<td>DFFDF</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td>FDDFF</td>
<td>Edison</td>
</tr>
<tr>
<td>FDDFFDF</td>
<td> </td>
<td>East</td>
<td>Washington</td>
</tr>
<tr>
<td rowspan = "3" style = " background-color: #F9F9F9; vertical-align: middle;">LION</td>
<td>GFFG</td>
<td>FGFGG</td>
<td>FGFG</td>
<td>FGGFGFG</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td>FGHGH</td>
<td>DDDFF</td>
</tr>
<tr>
<td></td>
<td>test2</td>
<td>FFGGFH</td>
<td>Washington</td>
</tr>
</tbody>
</table>
Спасибо, но особой разницы не вижу. Если я поищу Вашингтон, столбцы все равно сместятся. Я что-то пропустил?
Нет. Размах строк все портит.
Используйте tr { visibility: collapse; }
вместо tr { display: none; }
:
document.getElementById('search-input').addEventListener('keyup', searchTable);
function searchTable() {
const filter = this.value.toUpperCase();
let isMatch = false;
const tbody = document.querySelector('#example_full tbody');
const noMatch = document.getElementById('no-match');
if (!filter) {
tbody.querySelectorAll('tr').forEach(tr => {
tr.classList.remove('collapse', 'hidden');
});
noMatch.classList.remove('active');
return;
}
let rowspanEndIndex = 0;
tbody.querySelectorAll('tr').forEach((tr, index) => {
tr.classList.add('collapse');
tr.classList.remove('hidden');
if (rowspanEndIndex === index) {
rowspanEndIndex = 0;
}
tr.querySelectorAll('td').forEach(td => {
td.removeAttribute('hidden');
const rowspan = td.getAttribute('rowspan');
if (rowspan) {
rowspanEndIndex = index + Number(rowspan);
}
if (td.textContent && td.textContent.toUpperCase().includes(filter)) {
tr.classList.remove('collapse');
isMatch = true;
}
});
if (rowspanEndIndex) {
tr.setAttribute('data-group', rowspanEndIndex);
}
});
document
.querySelectorAll('#example_full tbody tr:has([rowspan])')
.forEach(tr => {
const group = tr.getAttribute('data-group');
const trs = tbody.querySelectorAll(`tr[data-group = "${group}"]`).length;
const collapseTrs = tbody.querySelectorAll(
`tr[data-group = "${group}"].collapse`,
).length;
if (trs !== collapseTrs) {
tr.classList.remove('collapse');
tr.querySelectorAll('td:not([rowspan])').forEach(td =>
td.setAttribute('hidden', true),
);
}
});
noMatch.classList.toggle('active', !isMatch);
}
.no-match {
color: red;
&:not(.active) {
display: none;
}
}
table {
border-collapse: collapse;
}
td,
th {
padding: 2px 8px;
}
th {
border: 1px solid #dddddd;
background-color: darkgray;
}
tr.collapse {
visibility: collapse;
}
<input
type = "text"
id = "search-input"
placeholder = "Search for records..."
/>
<p
id = "no-match"
class = "no-match"
>
No matching records found
</p>
<table id = "example_full">
<thead>
<tr>
<th>ABC</th>
<th>DEF</th>
<th>GHI</th>
<th>XXX</th>
<th>MMM</th>
</tr>
</thead>
<tbody>
<tr>
<td
rowspan = "4"
style = "vertical-align: middle"
>
MONKEY
</td>
<td>AD123</td>
<td>434SDD</td>
<td>DFDDFF</td>
<td>FDFFD</td>
</tr>
<tr>
<td>LEMON</td>
<td> </td>
<td>FDFGGF</td>
<td>DFFDF</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td>FDDFF</td>
<td>Edison</td>
</tr>
<tr>
<td>FDDFFDF</td>
<td> </td>
<td>East</td>
<td>LEMON</td>
</tr>
<tr>
<td>One tr</td>
<td> </td>
<td>LEMON</td>
<td>DDDFF</td>
</tr>
<tr>
<td
rowspan = "3"
style = "background-color: #f9f9f9; vertical-align: middle"
>
LION
</td>
<td>GFFG</td>
<td>FGFGG</td>
<td>FGFG</td>
<td>FGGFGFG</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td>FGHGH</td>
<td>DDDFF</td>
</tr>
<tr>
<td></td>
<td>test2</td>
<td>FFGGFH</td>
<td>Washington</td>
</tr>
</tbody>
</table>
Отличный. Отличная работа. Будь ты проклят! ;)
Отлично, большое спасибо. Это работает хорошо. Есть ли способ показать значение столбца ABC, если я ищу «Лимон». В столбце ABC должна отображаться Обезьяна. Спасибо.
Согласно вашему комментарию: «Есть ли способ показать значение столбца ABC, если я ищу «Лимон», вот решение, которое будет создавать и удалять ячейки и метки по мере необходимости. Я попытался добавить некоторые базовые комментарии к js-коду, чтобы объяснить, что происходит.
function searchTable() {
var input, filter, table, tr, th, td, i, j, txtValue, match, rowSpan, rowSpanData;
input = document.getElementById("searchInput");
filter = input.value.toUpperCase();
table = document.getElementById("example_full");
tr = table.getElementsByTagName("tr");
th = table.getElementsByTagName("th");
match = false;
rowSpan = 1;
rowSpanData = '';
for (i = 1; i < tr.length; i++) { // Skip the header row
tr[i].style.display = "none"; // Hide all rows initially
td = tr[i].getElementsByTagName("td");
//console.info("TD Length = " + td.length);
//Loop through the cells
for (j = 0; j < td.length; j++) {
if (td[j]) {
if (filter! = "") {
if (j==0 && td.length == th.length){
rowSpanData = td[j].innerHTML;
}
//If there is a match
txtValue = td[j].textContent || td[j].innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
//match boolean to be used for display of match message at end of fucntion
match = true;
if (td.length == th.length && td[0].hasAttribute("rowspan") && td[0].getAttribute("rowspan") != 1) {
td[0].setAttribute("originalRowSpan", td[0].getAttribute("rowspan"));
td[0].setAttribute("rowspan", 1);
}
if (td.length < th.length){
var newCell = tr[i].insertCell(0);
newCell.classList.add("removeMe");
newCell.innerHTML= rowSpanData;
}
// skip to the next row
continue;
} //end of match section
} else {
tr[i].style.display = "";
if (td[j].hasAttribute("rowspan")){
td[j].setAttribute("rowspan", td[j].getAttribute("originalRowSpan"));
} else if (td[j].classList.contains("removeMe")){
tr[i].deleteCell(0);
}
}
}
} // end of cell loop
} // end of row loop
// Show or hide the no match message
document.getElementById("noMatch").style.display = match ? "none" : "block";
}
.no-match {
display : none;
color : red;
}
th {
border-left : 1px solid #dddddd;
border-top : 1px solid #dddddd;
border-bottom : 1px solid #dddddd;
border-right : 1px solid #dddddd;
background-color: darkgray;
}
<input type = "text" id = "searchInput" placeholder = "Search for records..." onkeyup = "searchTable()" />
<p id = "noMatch" class = "no-match">No matching records found</p>
<table id = "example_full">
<thead>
<tr>
<th>ABC</th>
<th>DEF</th>
<th>GHI</th>
<th>XXX</th>
<th>MMM</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan = "4" style = " vertical-align: middle;">MONKEY</td>
<td>AD123</td>
<td>434SDD</td>
<td>DFDDFF</td>
<td>FDFFD</td>
</tr>
<tr>
<td>LEMON</td>
<td> </td>
<td>FDFGGF</td>
<td>DFFDF</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td>FDDFF</td>
<td>Edison</td>
</tr>
<tr>
<td>FDDFFDF</td>
<td> </td>
<td>East</td>
<td>Washington</td>
</tr>
<tr>
<td rowspan = "3" style = " background-color: #F9F9F9; vertical-align: middle;">LION</td>
<td>GFFG</td>
<td>FGFGG</td>
<td>FGFG</td>
<td>FGGFGFG</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td>FGHGH</td>
<td>DDDFF</td>
</tr>
<tr>
<td></td>
<td>test2</td>
<td>FFGGFH</td>
<td>Washington</td>
</tr>
</tbody>
</table>
Отлично работает, большое спасибо
Хорошо, когда ЛИМОН один))
Сделать это не так-то просто, но:
<TR>
имеет свойство hidden
, позволяющее показать/скрыть всю строку..rows
и .cells
.const
inSearch = document.querySelector('#search-input')
, msg_match = document.querySelector('#match-msg')
, expl_TB = document.querySelector('#example_full tbody')
;
function searchTable()
{
const
inFind = inSearch.value.trim()
, inRgx = new RegExp( inFind, 'gi')
;
expl_TB.querySelectorAll('td.matched').forEach( td => td.classList.remove('matched'));
expl_TB.querySelectorAll('tr') .forEach( tr => tr.hidden = false );
if ( inFind === '' ) // input is empty....
{
inSearch.value = '';
msg_match.classList.remove('noVisible');
return;
}
// find process...
let
matchingCount = 0
, rowParentIdxZ = 0
, rowParentLast = 0
, rowShowed = new Set()
;
for (let tr of expl_TB.rows )
{
let parent = getParentIdxZ( tr );
for (let td of tr.cells) // Find matching cells...
{
if (inRgx.test(td.textContent ))
{
matchingCount++;
td.classList.add('matched');
rowShowed.add(parent);
}
}
}
if ( matchingCount === 0) // no cells matching
{
msg_match.classList.remove('noVisible');
return;
}
msg_match.classList.add('noVisible');
for (let tr of expl_TB.rows ) // hide unmatched rows...
{
tr.hidden = !rowShowed.has( getParentIdxZ( tr ) );
}
function getParentIdxZ( tr ) // sub function...
{
let idxZ = tr.rowIndex -1; // use indexing where first index value is Zero;
if (tr.cells[0].rowSpan > 1 )
{
rowParentIdxZ = idxZ
rowParentLast = idxZ + tr.cells[0].rowSpan;
}
return (idxZ < rowParentLast) ? rowParentIdxZ : idxZ;
}
}
body {
font-family : Arial, Helvetica, sans-serif;
font-size : 14px;
}
table {
background : darkblue;
border-collapse : separate;
border-spacing : 1px;
}
th {
background-color : #7fccff;
padding : .4em .6em ;
}
td {
background-color : whitesmoke;
padding : .6em .4em;
}
.matched {
color : red;
background : lightgreen;
}
#match-msg {
margin-top : 0.3em;
margin-bottom : 1em;
padding-left : 2em;
color : darkblue;
}
.noVisible {
visibility : hidden;
}
<input id = "search-input" type = "text" placeholder = "Search for records..." onkeyup = "searchTable()" />
<p id = "match-msg" >No matching records found</p>
<table id = "example_full">
<thead>
<tr> <th>ABC</th><th>DEF</th><th>GHI</th><th>XXX</th><th>MMM</th> </tr>
</thead>
<tbody>
<tr><td rowspan = "4">MONKEY</td><td>AD123</td><td>434SDD</td><td>DFDDFF</td><td>FDFFD</td> </tr>
<tr><td>LEMON</td><td> </td><td>FDFGGF</td><td>DFFDF</td> </tr>
<tr><td> </td><td> </td><td>FDDFF</td><td>Edison</td> </tr>
<tr><td>FDDFFDF</td><td> </td><td>East</td><td>Washington</td> </tr>
<tr><td>a</td><td>Mister</td><td>Jojo</td><td>d</td><td>e</td> </tr>
<tr><td rowspan = "3">LION</td><td>GFFG</td><td>FGFGG</td><td>FGFG</td><td>FGGFGFG</td> </tr>
<tr><td> </td><td> </td><td>FGHGH</td><td>DDDFF</td> </tr>
<tr><td></td><td>test2</td><td>FFGGFH</td><td>Washington</td> </tr>
</tbody>
</table>
Строка с надписью «ОБЕЗЬЯНА» скрывается. При поиске «Вашингтон» отображается только одна строка, и в этой строке всего 4 столбца. (Вероятно, сейчас самое время начать знакомиться с инструментами отладки вашего браузера. В частности, с проводником DOM, который показывает текущее состояние документа, а также с отладчиком сценариев, который позволяет вам пошагово просматривать код и наблюдать точные изменения. оно творится.)