One filter function for multiple tables

Hi everyone,

I’m new to Javascript and am already running into a problem that i can’t seem to solve by myself.

I’ve got three functions. The first function is a filter function, which filters out a list and it works fine. The second function (onclick) then leads to a specific table. Works just fine as well.
Where my problem comes into play is the third function, the specific table with a filter element. There are going to be many tables so I can’t use document.getElementById. I did get it to work with alltables = document.querySelectorAll("table[data-name=mytable]"), but then it basically filters all tables in the background as well, which is not what I want. I tried to get it to work with document.getElementByClassName and by adding parameters to the function, but it just didn’t work out no matter what I tried. I just want the function to work with the specific table on screen.

I don’t know which of my attempts I should post codewise, but I guess document.getElementByClassName is the method to go, so this is what I have:

 <input class="country" type="text" placeholder="Search for names.." id="Supaland" onkeyup="myFunction('Supaland', 'supalandTable')">

  <table class="table" id="supalandTable">
    <tr>
function myFunction(countryName, tableName) {
  var input, filter, table, tr, td, i;
  input = document.getElementByClassName("country");
  filter = input.value.toUpperCase();
  table = document.getElementByClassName("table");
  tr = table.getElementsByTagName("tr");
  for (i = 0; i < tr.length; i++) {
    td = tr[i].getElementsByTagName("td")[0];
    if (td) {
      txtValue = td.textContent || td.innerText;
      if (txtValue.toUpperCase().indexOf(filter) > -1) {
        tr[i].style.display = "";
      } else {
        tr[i].style.display = "none";
      }
    }
  }
}

Any help would be highly appreciated! :slight_smile:

I don’t fully understand your description of what is going wrong.

Hi, thanks!
Well, the code I posted up there just doesn’t work ^^
When I first implemented the function the document.getElementById method was used, which worked perfectly fine because there was only 1 table.
But once I added another table, I couldn’t get it to work no more, meaning I can’t filter any table no more. I tried to rewrite the code with document.getElementbyClassName of which you can see a snippet up there, but I just don’t get it right.
I can post more code from the file if that is helpful

So the goal is to have multiple tables, which all get filtered by the same value?

Right now the reason it probably isn’t working is because you have the function wrong. It’s getElementsByClassName, not getElementByClassName.

Oh I wished that was the problem, but unfortunately it was just a typo.

The goal is to be able to filter each table individually by whatever the input is. There is always just one table “active” at once, depending on which item was chosen in the previous step.
I think I’m too much of a noob to explain it properly. Here’s some code that I think covers it all (the myFunction function is what bothers me):

<div> <input type="text" id="myInput" onkeyup="searchPeople()">
 <ul id="myUL">
  <li onclick="openPeople('Adele')">Adele</li>
<li onclick="openPeople('Agnes')">Agnes</li>
</ul>
</div>
<div id="Adele" class="people" style="display:none">

  <input class="country" type="text" id="Supaland" onkeyup="myFunction('Supaland', 'supalandTable')">

  <table class="table" id="supalandTable">
    <tr>
      <th>Name</th>
      <th>Country</th>
    </tr>
    <tr>
      <td>Foodtruck diaries</td>
      <td>USA</td>
    </tr>
  </table>
</div>

<div id="Agnes" class="people" style="display:none">
  <input class="country" type="text" id="Megaland" onkeyup="myFunction('Megaland', 'megalandTable')">

  <table class="table" id="megalandTable">
    <tr>
      <th>Name</th>
      <th>Country</th>
    </tr>
    <tr>
      <td>Taxi Driver</td>
      <td>Canada</td>
    </tr>
    </table>
</div>

<script>
function openPeople(peopleName) {
  var i;
  var x = document.getElementsByClassName("people");
  for (i = 0; i < x.length; i++) {
    x[i].style.display = "none";  
  }
  document.getElementById(peopleName).style.display = "block";  
}

function searchPeople() {
  var input, filter, ul, li, a, i;
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  ul = document.getElementById("myUL");
  li = ul.getElementsByTagName("li");
  for (i = 0; i < li.length; i++) {
    txtValue = li[i].textContent || li[i].innerText;
    if (txtValue.toUpperCase().indexOf(filter) > -1) {
      li[i].style.display = "";
    } else {
      li[i].style.display = "none";
    }
  }
}

function myFunction(countryName, tableName) {
  var input, filter, table, tr, td, i;
  input = document.getElementsByClassName("country");
  filter = input.value.toUpperCase();
  table = document.getElementsByClassName("table");
  tr = table.getElementsByTagName("tr");
  for (i = 0; i < tr.length; i++) {
    td = tr[i].getElementsByTagName("td")[0];
    if (td) {
      txtValue = td.textContent || td.innerText;
      if (txtValue.toUpperCase().indexOf(filter) > -1) {
        tr[i].style.display = "";
      } else {
        tr[i].style.display = "none";
      }
    }
  }
}
</script>

Thanks for the support :slight_smile:

Well, besides the fact that the method was spelled wrong, keep in mind that getElementsByClassName returns an array, not a single element.

Hmm ya but I cannot use document.getElementById to start with, because I can’t add elements or can I?
If I can’t specify an element with document.getElementsByClassName using additional parameters, then I really don’t know what else to try. When using alltables = document.querySelectorAll("table[data-name=mytable]") all tables in the file are filtered at once and that’s not the way it’s supposed to work. I mean I could write a function for each table with getElementById, but I guess that wouldn’t be good coding.

Any hint on how I have to approach this to get the filter function (myFunction) work for multiple tables?

@JuJu3 Can you walk me though what you want a user to be able to do here?

I am not understanding the purpose of the input box above the Adele and Agnes list items vs. the input box which appears above the Name and Country headers when clicking on either Adele and Agnes list items.

If you can explain what you want a user to be able to do (step by step), then I will try to guide you to some kind of solution.

Thanks Randell, that’s kind of you.

The user will first see a list, which in the code above consists of “Adele” and “Agnes”. The list is going to be long so i added the input function function searchPeople() so that the list can be filtered. This works just fine. Each element of the list as e.g. Agnes or Adele will will lead to a table through function openPeople(peopleName) and that works too. So there is going to be a table for each item in the first list. Now the tables gonna be big too, so I wanted to add another filter function myFunction(countryName, tableName) that can be used for each table individually. I guess the code for the filter table function must look like complete rubbish ^^, so this is where I started from:

 <input type="text" id="tableInput" onkeyup="myFunction()">
  <table id="myTable">

and

function myFunction() {
  var input, filter, table, tr, td, i;
  input = document.getElementById("tableInput");
  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];
    if (td) {
      txtValue = td.textContent || td.innerText;
      if (txtValue.toUpperCase().indexOf(filter) > -1) {
        tr[i].style.display = "";
      } else {
        tr[i].style.display = "none";
      }
    }
  }
}

It worked fine like this as long as I had only one table, let’s say the table for “Adele”, but once I tried to add a second table like for “Agnes”, I couldn’t get it to work no more. I guess I understood that it was due to the document.getElementById method, so I tried many different things, one of it is the version I posted in my first comment, but nothing got it to work :confused: