Using jQuery to Filter Table Rows

I’m retouching an old system, and though it could use a filter on it’s report page. The report has a large table with about 300 rows. After some play with jQuery, I came out with this little filter.
The project is using the .net GridView control, so I had limited control over the output HTML code. Still, I think this code can work for most tables. One thing to notice: you should use the class “filterable” on your table or on one of its parents for the code to work.
First, we need a text box:

Filter:
<input type="text" id="FilterTextBox" name="FilterTextBox" />

And the code:

$(document).ready(function(){
 //add index column with all content.
 $(".filterable tr:has(td)").each(function(){
   var t = $(this).text().toLowerCase(); //all row text
   $("<td class='indexColumn'></td>")
    .hide().text(t).appendTo(this);
 });//each tr
 $("#FilterTextBox").keyup(function(){
   var s = $(this).val().toLowerCase().split(" ");
   //show all rows.
   $(".filterable tr:hidden").show();
   $.each(s, function(){
       $(".filterable tr:visible .indexColumn:not(:contains('"
          + this + "'))").parent().hide();
   });//each
 });//key up.
});//document.ready

Explanation:

  1. Create Index Column – lines 2-7 – The jQuery “:contains()” selector is case sensitive, so at the first step I create another column on the table, than contains the whole row’s text on lowered case. On line 3 you may have noticed I’m filtering only rows that has <td>, to avoid hiding the header column (presumably, the header only has <th>). Later, I could make searches in this column alone. This works as long as the text on the table doesn’t change.
  2. Bind the Key-Up Event – lines 8-16.
  3. Make an array with all filter keywords – line 9 – Get all word from the text box and put them in an array. Again, I’m using toLowerCase() because “:contains” is case sensitive.
  4. Hide rows – lines 12-15 – I’m using jQurey’s each function to go through the array, and hiding all rows that don’t contain the current keyword (Assuming AND between all words).

That’s it. Now rows on our table can be filtered.

About these ads

25 thoughts on “Using jQuery to Filter Table Rows

  1. Pingback: [Tips] Filtrar un Gridview con Jquery al presionar una tecla :) - Chalalo Land

    • Thanks John!
      For OR you’ll have to reverse the logic – hide all rows, and then show rows that contain each word.
      Just replace .show() and :visible with .hide and :hidden (and vice versa).

    • Good point – you’d want to display rows if they do contain the word.
      Well, the good thing about jQuery is that there are only three lines doing the filtering – it’s easy to understand.
      Thanks John!

  2. Kobi, this does not work for me in IE. Especially when you press backspace or esc key the list get stuck at the filtered item.

    Please help. Thanks

  3. Nice code. Works perfectly.

    One helpful addition. I am building a “Check to email these people” list and need to block anyone who may have already been checked before the filter results hid them. (Because even though they’re hidden, the checkbox is still active.) I did this easily by adding a “disable” command after your line 14:

    $(‘.filterable tr:hidden :input’).attr(‘disabled’, true);

    and adding a re-enable line after your line 11:

    $(‘.filterable tr:visible :input’).removeAttr(‘disabled’);

  4. Hey, hello

    I have a question, I implement this in my web page but I have a Update panel for all my code, inside I have a Textbox that is the Filter, and the grid, but with the Update Panel doesn’t work, if I quit the Update Panel it works fine, any Idea about this?

    • Hello Alfonso,
      When you use an Update Panel you keep recreating the grid, so the meta data is lost (in this case, the extra column). You need to recreate it on updates, or even create the column on server side. You may find another grid-filtering method better though, this method has relatively an expensive first-time run, so it may be slower if you keep update the grid.

  5. I have a question,

    Is it possible to create a link to clear the text in the box when clicked? I don’t want to use a button.

    • Hello Ryan,
      Everything is possible, and this one is quite easy. First, add the link:

      <a href="#" class='clear' rel="nofollow">Clear</a>
      

      Next, bind the event on $(document).ready :

      $(".clear").click(function(){
          $("#FilterTextBox").val("").keyup();
          return false;
        });

      And that’s it. Working example: http://jsbin.com/anibe/2

  6. Kobi, this is great. This was pretty straight forward. I have been working on a project for our library, and was able to develop a filter based off your examples. Do you mind if I repost to a wiki, if I include your name and link here for credit for the original code?

    Christopher

    • Hello Christopher!
      I’m surprised this post is still so useful – I wrote this code a long time ago (I didn’t even knew regular expressions at the time, which could have been useful here). Actually, I’d think there are better alternatives by now, maybe using the .data helpers, or plain javascript object – but then again, maybe sometimes the simple approach works best.
      To your question – I have this (not-too-active) blog to help others – feel free to use this code in any way you see fit (and a link would be nice! and everyone just loves to see their names on the internet! so thanks!)

      Thanks!

  7. there’s a flaw in the script when you try to filter content containing: ‘
    fix:

    wrap this:
    $(“.filterable tr:visible .indexColumn:not(:contains(‘”
    + this + “‘))”).parent().hide();

    into:
    if (this + ” !== ”) {
    $(“.filterable tr:visible .indexColumn:not(:contains(‘”
    + this + “‘))”).parent().hide();
    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s