Blog: Example – Use a text box to filter through multiple items in a list (More Posts)
In my last blog, I shared about how I was using my local server to organise projects “locally”, that is on my PC and Laptop, as a way to curate and access my many, many projects of work. I used JavaScript and JSON to create a structured list that I could iterate through.
But it’s one thing to generate this list. Such a long list of data needs a filter so you can quickly access the information you actually need. This could be done by querying a MySQL database. Or you can use a text box to filter out all the data so you don’t need to do so much scrolling. That’s what I’m going to do in this blog.
We already have JSON data which at the time of writing has just a little less than 180 items. That’s fine for my purposes, but we really ought to have a way to access the data we want, without the need for so much scrolling. We want to keep the data but want to be able “query” it.
Let’s start by adding our input text box.
<input type="text" id="filter_input" placeholder="Search for names..">
The filterable area we want is any of the table rows. Luckily the table I created has a <tbody> element with an ID attribute. So we can select that.
<tbody id="project-table-body">
<!-- Rows will be inserted here -->
</tbody>
filterTableBody = document.getElementById("project-table-body");
Next, we need to select the filter text box in our script.
input = document.getElementById('filter_input');
The code below works by looking at the text content of the assigned variables in JavaScript and it examines the keystrokes of the text box. By doing this, it filters out the inner content of the table that does not match those keystrokes.
The content we want to filter is actually the first column of the table… the project title.
<table>
<thead>
<tr>
<th>Title</th>
<th>Directory</th>
<th>Local</th>
<th>FPOTD</th>
<th>Online</th>
<th>Portfolio</th>
<th>Ready</th>
</tr>
</thead>
<tbody id="project-table-body">
<!-- Rows will be inserted here -->
</tbody>
</table>
And it’s in the table body where we’ll be putting our searchable data. in the first column. Where the filter doesn’t find ant matches it will filter out the entire row too, which is the effect we’re looking for.
<table>
. . .
<tbody id="project-table-body">
<!-- Rows will be inserted here -->
<tr>
<td>JGDM Website</td>
. . .
</tr>
<tr>
<td>Bootstrap Project</td>
. . .
</tr>
</tbody>
</table>
Let’s make those selections now and tell JavaScript where to search for data to filter. We want to search for the table row inside the table body area.
table = document.getElementById("project-table-body");
tr = table.getElementsByTagName("tr");
Now for the bulk of the application. Use a for loop to iterate through all the data
for (i = 0; i < tr.length; i++) {
//
}
Inside the for loop, we tell JavaScript which column we are searching selecting all table cell elements and passing in the array index.
td = tr[i].getElementsByTagName("td")[0];
Finally, we perform the filtering by changing the display and text content properties of the table cells if they do not match the textbox keystrokes.
We check the values of the table cells with the txtValue variable.
The filter variable is what tracks the keystrokes of the single text box.
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
We just need to define all these variables at the top of the script file, if we haven’t done so already.
// Declare variables
var input, filter, table, tr, td, i, txtValue;
Put this all into a function and assign the function to a click event on the text box.
function filterText() {
// Declare variables
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("filter_input");
filter = input.value.toUpperCase();
table = document.getElementById("project-table-body");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
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";
}
}
}
}
onkeyup="filterText()"
<input type="text" id="filter_input" onkeyup="filterText()" placeholder="Search for names..">
We can use the onkeyup event on #filter_input to trigger the function on each keystroke.
In conclusion
And that is one way of creating a filterable text box. I like this method as it is instant and responsive to each press of a key, meaning if the search term you want is there, you can find it in just a few seconds.
My source, which I adapted for this example, is from the w3Schools code which you can try for yourself here!


