How do I search all the columns in the HTML table. My table has multiple <th> rows

Viewed 64

What is the best way to search all the columns in my HTML table? Currently, my table only searches the first column.

Additionally, my table has multiple header rows. I am not sure what is the best way to display search results if the results are only for certain header sections. Only the related headers should be displayed with the search results.

https://codepen.io/magic12/pen/QWmvGBX

function myFunction() {
  var input, filter, table, tr, td, i, txtValue;
  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];
    if (td) {
      txtValue = td.textContent || td.innerText;
      if (txtValue.toUpperCase().indexOf(filter) > -1) {
        tr[i].style.display = "";
      } else {
        tr[i].style.display = "none";
      }
    }
  }
}
table.table_brdr td {
  padding: 8px 10px;
  border: none;
}

table.table_brdr th {
  background-color: #a6a6a6;
  color: black;
}

tr:nth-of-type(odd) {
  background-color#D3D3D3;
}

#myInput {
  background-image: url('/css/searchicon.png');
  background-position: 10px 10px;
  background-repeat: no-repeat;
  width: 20%;
  font-size: 16px;
  padding: 12px 20px 12px 40px;
  border: 1px solid #ddd;
  margin-bottom: 12px;
}
<p>
  <input
    type="text"
    id="myInput"
    onkeyup="myFunction()"
    placeholder="Search"
    title="Searche"
  />
</p>
<table class="table_brdr" id="myTable">
  <tbody>
    <tr>
      <th>Column1</th>
      <th><strong>Column2</strong></th>
      <th>Column3</th>
    </tr>
    <tr>
      <td>abc</td>
      <td>xyz</td>
      <td>03/30/2017</td>
    </tr>
    <tr>
      <td>test12</td>
      <td>https://www.yahoo.com/</td>
      <td>03/30/2017</td>
    </tr>
    <tr>
      <th>Column1</th>
      <th>New Column</th>
      <th>Column3</th>
    </tr>
    <tr>
      <td>John</td>
      <td>abctd</td>
      <td>09/30/2019</td>
    </tr>
    <tr>
      <th>Column1</th>
      <th>New Column2</th>
      <th>Column3</th>
    </tr>
    <tr>
      <td>Doe</td>
      <td>abctd</td>
      <td>06/30/2019</td>
    </tr>
  </tbody>
</table>

3 Answers

This is the culprit

 td = tr[i].getElementsByTagName("td")[0];

Try this and let me know.

<script>
    function myFunction() {
        var input, filter, table, tr, td, i, txtValue;
        input = document.getElementById("myInput");
        filter = input.value.toUpperCase();
        table = document.getElementById("myTable");
        tr = table.getElementsByTagName("tr");
        for (i = 0; i < tr.length; i++) {
            var allTDs = tr[i].getElementsByTagName("td");

            for (index = 0; index < allTDs.length; index++) {
                txtValue = allTDs[index].textContent || allTDs[index].innerText;
                if (txtValue.toUpperCase().indexOf(filter) > -1) {
                    tr[i].style.display = "";
                    break;
                } else {
                    tr[i].style.display = "none";
                }
            }
        }
    }

</script>
<p><input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search" title="Searche"></p>
<table class="table_brdr" id="myTable">
    <tbody>
        <tr>
            <th>Column1</th>
            <th>Column2</th>
            <th>Column3</th>
        </tr>
        <tr>
            <td>abc</td>
            <td>xyz</td>
            <td>03/30/2017</td>
        </tr>
        <tr>
            <td>test12</td>
            <td>https://www.yahoo.com/ </td>
            <td>03/30/2017</td>
        </tr>
        <tr>
            <th>Column1</th>
            <th>New Column</th>
            <th>Column3</th>
        </tr>
        <tr>
            <td>John</td>
            <td>abc
            <td>09/30/2019</td>
        </tr>
        <tr>
            <th>Column1</th>
            <th> New Column2</th>
            <th>Column3</th>
        </tr>

        <tr>
            <td>Doe</td>
            <td>abctd </td>
            <td>06/30/2019</td>
        </tr>

    </tbody>
</table>

You could use tr.innerText to get all the text content of that table row. Then do your usual comparison.

function myFunction() {
    const input = document.getElementById("myInput");
    const filter = input.value.toUpperCase();
    const table = document.getElementById("myTable");
    const tr = table.getElementsByTagName("tr");
    for (let i = 0; i < tr.length; i++) {
        const txtValue = tr[i].innerText.toUpperCase();
        if (txtValue.indexOf(filter) > -1) {
            tr[i].style.display = "";
        } else {
            tr[i].style.display = "none";
        }
    }
}

Since filtering under each header, and then hiding the whole row for non-matches seems not very helpful, this example highlights matches within the table. If you still want to remove rows let me know, it should be simple.

Details are commented in the example

// Reference <form> and <table>
const form = document.forms.UI;
const table = document.querySelector("table");
// Bind <form> to the submit event
form.onsubmit = searchTable;
/*
Event handler passes Event Object by default
A. Stop the <form> from sending data to server
Reference all form controls
Get the string value from <input>
D. Split it up and re-join it into "xxx|xxx" pattern
Collect all <td> into an array
Declare some variables
G. Iterate through array of <td>
Store text of current <td>
If there is text in the current <td>...
...define a RegExp that matches the <input> value...
...then split the string into an array and then
replace matches with the same text with <mark>
tag wrapped around it
Finally render the string into HTML
*/
function searchTable(event) {
  event.preventDefault(); // A.
  const IO = this.elements;
  let terms = IO.search.value;
  terms = terms.split(' ').join('|'); // D.
  const tCells = [...table.querySelectorAll('td')];
  let text, rgx, match;
  // G.
  tCells.forEach((td, idx) => {
    text = td.textContent;
    if (text.length > 0) {
      rgx = new RegExp(`(${terms})`, 'gim');
      match = text.split(' ').join(' ').replace(rgx, `<mark>$1</mark>`);
    }
    td.innerHTML = match;
  });
}
*,
*::before,
*::after {
  margin: 0;
  box-sizing: border-box
}

html {
  font: 300 2ch/1.2 'Segoe UI';
}

fieldset {
  display: flex;
  width: max-content;
  margin: 20px auto;
}

button,
input {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  width: max-content;
  height: 2rem;
  padding: 4px 8px;
  font: inherit;
}

button:hover {
  cursor: pointer;
}

#search {
  width: 75%;
  margin-bottom: 12px;
  border: 1px solid #ddd;
}

td {
  padding: 8px 10px;
  border: none;
}

th {
  padding: 8px 10px;
  background-color: #a6a6a6;
  color: #930;
}

tr:nth-of-type(odd) {
  background-color: #D3D3D3;
}

mark {
  font-weight: 900;
  color: red;
}
<form id='UI'>
  <fieldset>
    <input id="search" name="search" placeholder="Enter search terms here..." title="Search Table" type="search">
    <button>Search&nbsp;</button>
  </fieldset>
</form>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Description</th>
      <th>Date</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Darrel Legier</td>
      <td>suscipit a feugiat et eros vestibulum ac est lacinia nisi venenatis tristique</td>
      <td>5/5/2022</td>
    </tr>
    <tr>
      <td>Ambur Samett</td>
      <td>interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at</td>
      <td>8/27/2021</td>
    </tr>
    <tr>
      <th>Name</th>
      <th>Description</th>
      <th>Date</th>
    </tr>
    <tr>
      <td>Howard Varney</td>
      <td>aenean auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit</td>
      <td>11/4/2021</td>
    </tr>
    <tr>
      <td>Ferrell Ravenscroft</td>
      <td>accumsan felis ut at dolor quis odio consequat varius integer ac leo</td>
      <td>4/14/2022</td>
    </tr>
    <tr>
      <td>Zuzana Duckhouse</td>
      <td>mauris eget massa tempor convallis nulla neque libero convallis eget eleifend luctus ultricies eu nibh</td>
      <td>12/16/2021</td>
    </tr>
    <tr>
      <th>Name</th>
      <th>Description</th>
      <th>Date</th>
    </tr>
    <tr>
      <td>Berenice Pawel</td>
      <td>quam sapien varius ut blandit non interdum in ante vestibulum ante ipsum primis in</td>
      <td>06/30/2019</td>
    </tr>
    <tr>
      <td>Janith Screach</td>
      <td>quam sapien varius ut blandit non interdum in ante vestibulum ante ipsum primis in</td>
      <td>06/30/2019</td>
    </tr>
  </tbody>
</table>

Related