I used w3School code for my page and it works fine but it only filters one column, don’t know how create loops but hopping there is easier solution.
td =
Here is correct function
function myFunction() {
var input = document.getElementById("myInput");
var filter = input.value.toUpperCase();
var table = document.getElementById("myTable");
var tr = table.getElementsByTagName("tr");
for (var i = 0; i < tr.length; i++) {
if (tr[i].textContent.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
Should be tr[i].textContent
You just need to add another loop to go over the cells, so:
table = document.getElementById("myTable");
// tr = table.getElementsByTagName("tr");
// Easier to use the rows collection:
var tr = table.rows;
for (i = 0; i < tr.length; i++) {
// Easier to use the cells collection
// td = tr[i].getElementsByTagName("td")[0];
cells = row.cells;
// Loop over all the cells
for (var j=0, jLen=cells.length; j<jLen; j++) {
td = cells[j];
// Existing loop
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
Your code is fine. To add multiple columns you need to add ||
condition (in if clause).
The problem with Rob's answer is it will filter out table headings if you use tr.
Here is extension to code:
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]; // for column one
td1 = tr[i].getElementsByTagName("td")[1]; // for column two
/* ADD columns here that you want you to filter to be used on */
if (td) {
if ( (td.innerHTML.toUpperCase().indexOf(filter) > -1) || (td1.innerHTML.toUpperCase().indexOf(filter) > -1) ) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
function filterTable(event) {
var filter = event.target.value.toUpperCase();
var rows = document.querySelector("#myTable tbody").rows;
for (var i = 0; i < rows.length; i++) {
var firstCol = rows[i].cells[0].textContent.toUpperCase();
var secondCol = rows[i].cells[1].textContent.toUpperCase();
if (firstCol.indexOf(filter) > -1 || secondCol.indexOf(filter) > -1) {
rows[i].style.display = "";
} else {
rows[i].style.display = "none";
}
}
}
document.querySelector('#myInput').addEventListener('keyup', filterTable, false);
<input id="myInput" type="text" />
<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>
Code that works for filtering multiple columns dynamically. No changes needed.
function myFunction(elem) {
var input, filter, table, tr, td, i, txtValue;
input = elem;
filter = input.value.toUpperCase();
table = document.getElementById("YourTableId");
tr = table.getElementsByTagName("tr");
for (i = 1; i < tr.length; i++) {
tds = tr[i].getElementsByTagName("td");
var matches = false;
for (j = 0; j < tds.length; j++) {
if (tds[j]) {
txtValue = tds[j].textContent || tds[j].innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
matches = true;
}
}
}
if(matches == true)
{
tr[i].style.display = "";
}
else {
tr[i].style.display = "none";
}
}
}
There are significantly better resources on the web than W3 Schools, you really should avoid that website IMO. That being said, you just need to look at tr
rather than one of the td
s if you want to match the whole row:
function myFunction() {
var input = document.getElementById("myInput");
var filter = input.value.toUpperCase();
var table = document.getElementById("myTable");
var tr = table.getElementsByTagName("tr");
for (var i = 0; i < tr.length; i++) {
if (tr.textContent.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
If you want to filter multiple columns instead of the whole row, just use OR (||
) in your condition:
function myFunction() {
var input = document.getElementById("myInput");
var filter = input.value.toUpperCase();
var table = document.getElementById("myTable");
var tr = table.getElementsByTagName("tr");
var tds = tr.getElementsByTagName('td');
for (var i = 0; i < tr.length; i++) {
var firstCol = tds[0].textContent.toUpperCase();
var secondCol = tds[1].textContent.toUpperCase();
if (firstCol.indexOf(filter) > -1 || secondCol.indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
Some reasons why this tutorial isn't great: you should avoid using innerHTML
and should instead use textContent
since it's possible that your cells will have HTML and the user could type a tag name when trying to search for visible text and be confused by what is matching. You should give your functions names that indicate what they do (e.g. filterTable
instead of myFunction
). Additionally, there are easier ways to access table data (e.g. tr.cells
). If you add a keyup
event listener to #myInput
you will not need to lookup that DOM node everytime the function is called. Here is an example:
function filterTable(event) {
var filter = event.target.value.toUpperCase();
var rows = document.querySelector("#myTable tbody").rows;
for (var i = 0; i < rows.length; i++) {
var firstCol = rows[i].cells[0].textContent.toUpperCase();
var secondCol = rows[i].cells[1].textContent.toUpperCase();
if (firstCol.indexOf(filter) > -1 || secondCol.indexOf(filter) > -1) {
rows[i].style.display = "";
} else {
rows[i].style.display = "none";
}
}
}
document.querySelector('#myInput').addEventListener('keyup', filterTable, false);
<input id="myInput" type="text" />
<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>