Adding Searching to the TableListJS HTML5 Component


In a previous article, I introduced a scrollable HTML multi-column table with selectable rows. In effect, the HTML table becomes a scrollable, multi-column list that you can use in forms where the user can make a selection. In this blog, we’ll add a search box (outlined in red in Figure 1) to provide searching and filtering to the list to quickly find entries without scrolling and hunting.

Figure 1 – The TableListJS HTML component with an integrated search field

First, the HTML for this is similar to the previous article, with the single addition of an HTML field, highlighted in bold in Listing 1.

Searchable TableListJS By Eric Bruno




Column 1 Column 2 Column 3
Entry 1 Entry 2 Entry 3


Listing 1 – Snippet of HTML code for the TableListJS component with search field

Next, to handle the keyboard input from the search field, we add a JavaScript function to the updated tablelist.js file (introduced previously) to insert a keyboard handler (see Listing 2). This only needs to be done once, so there’s a flag (initComplete) to indicate this. This flag is checked elsewhere.

function initTableJS() {
    initComplete = true;
    // Look for input box and insert key handler
    var prevTxt = null;
    var txt = document.getElementsByName('filterTxt');
    if ( txt != null ) {
        for (var i = 0; i < txt.length; i++) {
            txt[i].onkeyup=function(event) {
                var e = event || window.event;
                var curTxt =;
                prevTxt = curTxt;
                return true;

Listing 2 – This initializer function inserts a keyboard handler for the TableListJS search field.

The initTableJS() function only needs to be called once. It searches for an element on the page with the name filterTxt (which was specified in the page HTML shown in Listing 1). Once found, a keyboard handler is added by assigning a function to the onkeyup() event. Let’s take a look at the custom keyboard handler, handleKeyPress(), now.

Inside the handleKeyPress() Function

Here are the overall steps that occur when a key is pressed within the field:

    1. Loop through all the rows in the list.
    2. Check each row to see if the columns contain the text entered, in any order. Example: typing “Bruno Eric” would match the list entry “Eric Bruno,” or even “Eric J. Bruno.” Either way, it would remain in the list.
    3. Remove (hide) rows that don’t match the search text.
    4. If the user hits the backspace key, restore the list to its full set of original entries, and search from the top again.

First, a check is made to see if the user hit the backspace key (see Listing 3). If so, the list’s entries are restored to display the entire set of entries, and filtering takes place on this restored list of entries. Otherwise, the list of entries is further filtered with each keystroke (more on that in a moment).

function handleKeyPress(oldVal, newVal) {
    var select = document.getElementById('entries');
    // If the number of characters in the text box is less than last time
    // it must be because the user pressed delete
    if ( oldVal !== null && (newVal.length < oldVal.length) ) {
        // Restore the lists original set of entries
        // and start from the beginning
        for ( i = 1; i < select.rows.length; i++ ) {
            select.rows[i].style.display = '';

Listing 3 – Part of the keyboard handler function, to handle the backspace key.

As characters are entered into the search field, the list is continuously filtered to match what’s been entered so far. If you type multiple words or characters separated by spaces, they’re split up using the JavaScript split() function. Each list row that does NOT contain all of the words entered (regardless of order) is marked to not be displayed:

    // Break out all of the parts of the search text by splitting
    // on white space
    var parts = newVal.split(' ');
    // Interate through each row and filter out the entries that
    // don't contain the entered text
    for ( i = 1; i < select.rows.length; i++ ) {
        var entry = select.rows[i];
        if ( === 'none' ) {
        var rowMatch = true;
        // Compare each part of the entered text to each cell's text
        for ( p = 0; p < parts.length; p++ ) {
            // The row needs to contain all portions of the
            // search string *but* in any order
            var part = parts[p].toUpperCase();
            var partMatch = false;
            // don't search on space or null
            if ( part !== ' ' && part !== '' ) {
                // Iterate through each column (cell) per row
                for ( c = 0; c < entry.cells.length; c++ ) { var entryTxt = entry.cells[c].innerHTML; if ( entryTxt.toUpperCase().lastIndexOf(part) >= 0 ) {
                    partMatch = true;
            if ( partMatch === false ) {
                // Cycled through all cells and didn't find
                // a match for this part, so this row needs
                // to be deleted
                rowMatch = false;

There are some things to point out in this code before we continue. First, since each list “row” is really made up of multiple table column entries, each column’s text needs to be checked against each search term entered. Therefore, there are three nested loops: the first iterates each row, the second iterates each of the search terms (separated by spaces), and the third iterates each column in the current row. If each of the search terms matches entries across all of the row’s columns, then that row is kept in the list. If the aggregation of a row’s column entries doesn’t match all of the search terms, that row is marked for removal from the list:

    if ( rowMatch === false ) {
        select.rows[i].style.display = 'none';

The entries aren’t really removed—They’re just marked to not be displayed. This makes it easy to restore them as the text in the search box is deleted.

Here’s the list in action, although you should try it for yourself. The screenshot below shows the result after typing “4” into the search field:

The screenshot below shows the result after typing “E” into the search field:

If you type “E 4” (or “e 4”), then there are no matches, because there are no rows that contain words with both the letter “e” and the number “4” in them:

That’s it! You can download the updated TableListJS code along with a sample HTML page here to try it in action. In my experience, it’s a very dynamic way of filtering items in a long list, and users have liked it. The fact that it’s combined with the multi-column, scrollable table makes it a very useful HTML component.

Eric Bruno is a contributing editor to multiple publications with more than 20 years of experience in the information technology community. He is a highly requested speaker and writer for topics spanning the technology spectrum, from mobile to the data center. Eric is a regular contributor at Fixate IO.


Click on a tab to select how you'd like to leave your comment

Leave a Comment

Your email address will not be published.

Skip to toolbar