1

Basing on How to filter a html table using simple javascript? I want to filter my html table with cells linked to urls. How to prevent background urls being filtered also?

Here on example when I search for "sweden" it also shows "Germany" because "Germany" is linked to https://germany.net/sweden in the table

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 (var i = 0; i < tr.length; i++) {
    var tds = tr[i].getElementsByTagName("td");
    var flag = false;
    for(var j = 0; j < tds.length; j++){
      var td = tds[j];
      if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
        flag = true;
      } 
    }
    if(flag){
        tr[i].style.display = "";
    }
    else {
        tr[i].style.display = "none";
    }
  }
}
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names then click to launch.." title="Type in a name">

<table id="myTable">
  <tr class="header">
    <th style="width:60%;">Name</th>
    <th style="width:40%;">Country</th>
  </tr>
  <tr>
    <td>Alfreds Futterkiste</td>
    <td><a href="https://germany.net/sweden">Germany</a></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>
</table>
</body>
</html>

Update: Additional question - would it be possible to filter basing on column name also? So, for example in filter field use eg. Country:ger to find all rows containing string ger in column "Country"?

Chris
  • 939
  • 2
  • 11
  • 22

3 Answers3

1

Change innerHTML to innerText so avoid including the link in your filter.

Side note: This will only work if you want to make sure HTML elements are not including in your search. If your use-case grows beyond this you will need the data in a different structure (like JSON) to filter through that will also generate the table.

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 (var i = 0; i < tr.length; i++) {
    var tds = tr[i].getElementsByTagName("td");
    var flag = false;
    for(var j = 0; j < tds.length; j++){
      var td = tds[j];
      if (td.innerText.toUpperCase().indexOf(filter) > -1) {
      //      ^-- I changed this
        flag = true;
      } 
    }
    if(flag){
        tr[i].style.display = "";
    }
    else {
        tr[i].style.display = "none";
    }
  }
}
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names then click to launch.." title="Type in a name">

<table id="myTable">
  <tr class="header">
    <th style="width:60%;">Name</th>
    <th style="width:40%;">Country</th>
  </tr>
  <tr>
    <td>Alfreds Futterkiste</td>
    <td><a href="https://germany.net/sweden">Germany</a></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>
</table>
</body>
</html>
Dominik
  • 6,078
  • 8
  • 37
  • 61
0
use textContent instead of innerHtml.

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 (var i = 0; i < tr.length; i++) {
        var tds = tr[i].getElementsByTagName("td");
        var flag = false;
        for(var j = 0; j < tds.length; j++){
          var td = tds[j];
         console.log(td.textContent);

          if (td.textContent.toUpperCase().indexOf(filter) > -1) {
            flag = true;
          } 
        }
        if(flag){
            tr[i].style.display = "";
        }
        else {
            tr[i].style.display = "none";
        }
      }
    }
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
    <html>
    <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
    <input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names then click to launch.." title="Type in a name">

    <table id="myTable">
      <tr class="header">
        <th style="width:60%;">Name</th>
        <th style="width:40%;">Country</th>
      </tr>
      <tr>
        <td>Alfreds Futterkiste</td>
        <td><a href="https://germany.net/sweden">Germany</a></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>
    </table>
    </body>
    </html>
Tushar Wasson
  • 494
  • 5
  • 10
0

The issue is using textContent instead of innerHTML

Here is a modern version

const search = document.getElementById("myInput");

const toggle = () => {
  const text = search.value.toUpperCase();
  const rows = [...document.querySelectorAll("#myTable tr")]

  rows.forEach(tr => {
    const show = [...tr.querySelectorAll("td")].filter(td => {
      return td.textContent.toUpperCase().includes(text)
    }).length > 0

    tr.classList.toggle("hide", text && !show)
  })
}

search.addEventListener('keydown', ({ key }) => {
  if (["Backspace", "Delete"].includes(key))  toggle()
})

search.addEventListener('input', toggle)
.hide {
  display: none
}
<input type="text" id="myInput" autocomplete="off" placeholder="Search for names then click to launch.." title="Type in a name">

<table>
  <thead>
    <tr class="header">
      <th style="width:60%;">Name</th>
      <th style="width:40%;">Country</th>
    </tr>
  </thead>
  <tbody id="myTable">
    <tr>
      <td>Alfreds Futterkiste</td>
      <td><a href="https://germany.net/sweden">Germany</a></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>
mplungjan
  • 169,008
  • 28
  • 173
  • 236