My WebDev Notes: Filter table

Habdul Hazeez - Apr 1 '20 - - Dev Community

Check the filter table online: https://ziizium.github.io/my-webdev-notes/filtertable/

Tables contain data and you might find yourself in a situation where the data on a single is quite much even if you employ pagination.

Web applications like phpMyAdmin employ a particular feature of filtering database names as you type without the need for a page refresh.

An image of phpmyadmin web application showing database names in their unfiltered form
Unfiltered database names in phpMyAdmin

An image of phpmyadmin web application showing database names in their filtered form
Filtered database names in phpMyAdmin

This experiment is about recreating that feature using HTML, CSS, and JavaScript.


The HTML will have a form which in turn will contain a single form input and the table that's going to be filtered.

<main>
    <h1>Programming languages</h1>

    <form>
        <label for="searchInput">Enter search term: </label>
        <input type="text" id="searchInput" class="searchInput" placeholder="Search by Language" title="Type a Programming Language">
    </form>

    <table class="table" id="table">
     <tbody>
     <thead>
        <tr class="header">
            <th>Programming Language</th>
            <th>Inventor</th>
        </tr>
     </thead>

     <tr>
        <td>JavaScript</td>
        <td>Brendan Eich</td>
     </tr>

     <tr>
        <td>Python</td>
        <td>Guido van Rossum</td>
     </tr>

     <tr>
        <td>C</td>
        <td>Dennis Ritchie</td>
     </tr>

      <tr>
        <td>PHP: Hypertext Preprocessor</td>
        <td>Rasmus Lerdorf</td>
      </tr>

         <!-- You can search online for other programming languages and their creator -->
         </tbody>
    </table>
Enter fullscreen mode Exit fullscreen mode

The following CSS snippet is for cosmetics:

/**
  * CSS for cosmetics
  */
h1 {
    text-align: center;
}

label {
    font-size: 1.5em;
    margin-bottom: 0.7em;
}

form {
    margin-bottom: 1em;
}

th,
td {
    text-align: left;
    padding: 0.75em;
}

tr {
    border-bottom: 1px solid #ddd;
}

tr.header,
tr:hover {
    background-color: #f1f1f1;
}

.header th:nth-child(1) {
    width: 60%;
}

.header th:nth-child(2) {
    width: 40%;
}

.searchInput {
    width: 60%;
    font-size: 1em;
    padding: 0.6em;
    border: 1px solid #dddddd;
    margin-bottom: 0.75em;
}

.table {
    border-collapse: collapse;
    width: 100%;
    border: 1px solid #dddddd;
    font-size: 1.2em;
}
Enter fullscreen mode Exit fullscreen mode

JavaScript is the core part of the application that's going to make the filtering possible. Therefore, I am not writing it all at once rather we'll dissect it together to figure out why and how it works.

When you take a look at the HTML form input you will realize an HTML ID is attached to it. Here it is once again:

<!-- I have omitted other attributes of the input to keep things short -->

<input type="text" id="searchInput">
Enter fullscreen mode Exit fullscreen mode

Text entered into this form input will be used as the filter. We'll have to observe changes when a user types in this input and compare it against the data in the table. The best way to do this is to attach an event listener.

In JavaScript, we make use of the addEventListener method to attach an event to an HTML element. It accepts parameters like:

  • An HTML DOM Event
  • A function
  • A boolean value indicating whether to use event bubbling or event capturing

The particular event we'll have to watch out for is the keyup event because we'll have to make comparisons with the table when the user types.

The function (defined later) describes what happens when the user types.

We'll pass a false value as the third parameter to this function which means the event listener will use event bubbling

// get the form input
let searchInput = document.getElementById('searchInput');

// attach an event listener
searchInput.addEventListener("keyup", filterTable, false);
Enter fullscreen mode Exit fullscreen mode

Next we need to define the function filterTable. We'll start by doing the following:

  • Get the user input
  • Select the table
  • Select all table rows in the selected table
function filterTable() {
    // get the user input
    let filter = searchInput.value.toUpperCase();

    // grab the table
    let table = document.getElementById("table");

    // get all table rows in the selected table
    let tr = table.getElementsByTagName("tr");
}
Enter fullscreen mode Exit fullscreen mode

The getElementsByTagName() used in selecting the tr returns an HTMLCollection, if we are to make any comparison we'll have to loop through the collection.

Before that, we should know that the user will filter the table using the name of the programming language which is inside the first table data (td) of each row.

Therefore, when we perform the loop we'll have to select every first table data in each row:

function filterTable() {
    // previous code remain the same

    for (let i= 0; i < tr.length; i++) {

        // select every first table data in each row
        let td = tr[i].getElementsByTagName("td")[0];

        // more to follow

    }
}
Enter fullscreen mode Exit fullscreen mode

Now that we have the table data, we are ready to make a comparison. We check if the user input exists in the table row using the indexOf operator. If it exists we show the user and hide the remaining data in the table. A simple if/else will do the trick:

function filterTable() {
    // previous code remain the same

    for (let i= 0; i < tr.length; i++) {

        // previous code remain the same

        if (td) {
            if (td.innerHTML.toUpperCase().indexOf(filter) > -1) { // we found a match

                tr[i].style.display = "";

            } else { // no match found

                tr[i].style.display = "none";

            } // end of if(td.innerHTML...)

        } // end of if(td)

    } // end of for loop 

} // end of function filterTable()
Enter fullscreen mode Exit fullscreen mode

Here is the whole function:

function filterTable() {

    // get the user input
    let filter = searchInput.value.toUpperCase();

    // grab the table
    let table = document.getElementById("table");

    // get all table rows in the selected table
    let tr = table.getElementsByTagName("tr");

    for (let i= 0; i < tr.length; i++) {

        // get the first table data of each row
        let td = tr[i].getElementsByTagName("td")[0];

        if (td) { // we got a data to work with

            if (td.innerHTML.toUpperCase().indexOf(filter) > -1) { // we found a match

                // we show it
                tr[i].style.display = "";

            } else { // no match found

                // we hide the table data
                tr[i].style.display = "none";

            } // end of if (td.innerHTML..)

        } // end of if (td)

    } // end of for()

} // end of function filterTable()
Enter fullscreen mode Exit fullscreen mode

And the Github repo:

GitHub logo ziizium / my-webdev-notes

Code snippets for series of articles on DEV about my experiments in web development

My WebDev Notes

This repositiory contains code snippets, and links for series of articles on DEV about my experiments in Web development.

List of articles






Have fun!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .