1

I am using PHP and MySQL to build an HTML table. I am trying to use JavaScript to filter/search the table and only display the rows with the results I need. I want the JavaScript input to search multiple <td>s of the table. I was able to get this to work, but it is not going to be an elegant solution to put in place with larger tables.

I am sure there is a better way to choose what is being searched, but have not been able to find anything. Does anybody know a way for me to make this code more flexible for varying column width tables?

    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];
        td1 = tr[i].getElementsByTagName("td")[1];
        if (td+td1) {
          if ((td.innerHTML.toUpperCase().indexOf(filter)+td1.innerHTML.toUpperCase().indexOf(filter)) > -2) {
            tr[i].style.display = "";
          } else {
            tr[i].style.display = "none";
          }
        }       
      }
    }
    <input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search" title="Type in anything">
    
    <table id="myTable">
      <tr class="header">
        <th style="width:60%;">Name</th>
        <th style="width:40%;">Country</th>
      </tr>
      <tr>
        <td>North/South</td>
        <td>UK</td>
      </tr>
      <tr>
        <td>Paris specialites</td>
        <td>France</td>
      </tr>
    </table>
    

10
  • 2
    JavaScript !== Java Commented Jul 20, 2017 at 16:34
  • Separate your concerns. Build a function that builds table markup for given data and a separate function that filters your data and then uses the first function to replace your table markup with the new data. Commented Jul 20, 2017 at 16:38
  • I'm not sure how varying column widths apply to a search function. The content of the cell is what matters, not the width of the cell. Commented Jul 20, 2017 at 16:38
  • I am sorry, I meant varying number of columns in the table, not actual width of the table. Commented Jul 20, 2017 at 16:49
  • See my answer for a solution that works on any amount of columns. Commented Jul 20, 2017 at 16:56

2 Answers 2

3

There's a lot you can improve. Start by remembering to explicitly declare your variables, otherwise they become global.

This solution doesn't rely on any specific number of columns. It will work no matter how many there are.

See comments inline for more:

// Get DOM references just once:
var input = document.getElementById("myInput");
var table = document.getElementById("myTable");

// Do event binding in JavaScript, not HTML
input.addEventListener("keyup", filter);
input.addEventListener("search", filter);

// Get all rows, except the header and convert to array so .forEach() can be used to loop
var rows = Array.prototype.slice.call(table.querySelectorAll("tr:not(.header)"));  

function filter() {
  // Always trim user input
  var filter = input.value.trim().toUpperCase();

  // Loop the rows
  rows.forEach(function(row) {
  
    // You really don't need to know if the search criteria
    // is in the first or second cell. You only need to know
    // if it is in the row.
    var data = "";
    // Loop over all the cells in the current row and concatenate their text
    Array.prototype.slice.call(row.getElementsByTagName("td")).forEach(function(r){
      // Don't use .innerHTML unless there is HTML. Use textContent when there isn't.
      data += r.textContent;  
    });

    // Check the string for a match and show/hide row as needed
    // Don't set individual styles. Add/remove classes instead
    if(data.toUpperCase().indexOf(filter) > -1){
      // show row
      row.classList.remove("hidden");
    } else {
      // hide row
      row.classList.add("hidden");
    }
  });
  
}
input[type=search]{
  border-radius:10px;
  outline:0;
  padding:3px;
}

input[type=search]:focus{
  box-shadow:0 0 4px blue;
}

.hidden { display:none; }
.leftHeader { width:60%; }
.rightHeader { width:40%; }
<!-- Use the actual "search" input type and don't do inline CSS or JavaScript -->
<input type="search" id="myInput" placeholder="Search" title="Type in anything">
    
<table id="myTable">
  <tr class="header">
    <th class="leftHeader">Name</th>
    <th class="rightHeader">Country</th>
  </tr>
  <tr>
    <td>North/South</td>
    <td>UK</td>
  </tr>
  <tr>
    <td>Paris specialites</td>
    <td>France</td>
  </tr>
</table>

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the feedback, definitely gave me some things to improve and think about. This seems to work mostly, but it is getting rid of my header row.
@KennyBrown Oops. Slight oversight on my part. Easy fix. Check the updated answer.
0

All what you have to do is to get the td content and then match it with the search input.

function search(value) {
  $('table tr').each(function () {
    var content = $(this).find('td').text();
    if (content.toUpperCase().includes(value.trim().toUpperCase())) {
      $(this).show();
    } else {
      $(this).hide();
    }
  });

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<body>

<input type="search" placeholder="Search..." id="search_account" onkeyup="search(this.value)">

<table>
  <tr>
   <td>Cell1</td>
   <td>Cell2</td>
   <td>Cell3</td>
  </tr>
  <tr>
    <td>Cell4</td>
    <td>Cell5</td>
    <td>Cell6</td>
  </tr>
</table>

</body>
</html>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.