I needed to have a very lightweight and easy to use javascript table filter. The idea was to add a second row to the table header (below the column names) and have there a text input in each cell of this new row. When you write something in there and press Return, it will filter out all rows not containing this string in this particular column. You should also be able to combine filters for different columns.
Let’s implement it as a jQuery plugin. First we need a name… We’ll call the file jquery.filtertable.js and the function we define in the plugin will be filtertable:
(function($) {
$.fn.filterTable = function(filter, columnname) {
return this;
};
})(jQuery);
We have two parameters:
- First, the string used to filter the table
- Second, the name of the column where the filter string will be searched for
Of course using the column name is not always a good idea. It’s be better to use an ID or an index. An index is kind of difficult to use especially if columns are moved around. And since the column might not have an ID but will most probably have a name/header, I went for the name.
So the first thing we need to do is to map the column name to an internal index:
var index = null;
this.find("thead > tr:first > th").each(function(i) {
if ($.trim($(this).text()) == columnname) {
index = i;
return false;
}
});
So here I make a few assumptions:
- The table has a theader
- The first row in the this header is the one we’re interested in
If we do not find the column, we just throw an exception:
if (index == null)
throw ("filter columnname: " + columnname + " not found");
Then we loop through the rows, get the text of the corresponding cell and compare it with the filter. If it contains the filter, the row is shown otherwise hidden:
this.find("tbody:first > tr").each(function() {
var row = $(this);
var cellText = $(row.find(("td:eq(" + index + ")"))).text();
if (cellText.indexOf(filter) == -1) {
row.hide();
}
else {
row.show();
}
});
Note that I here also assume you have a <tbody> tag. If not, you’ll have to modify the plugin.
There are 2 additional pieces of functionality we’ll want to add:
- If the filter string is empty, we show everything
- If the cell contains a select box, we want to use the text of the selected entry and cell text
First the empty filter showing all rows:
this.find("tbody:first > tr").each(function() {
var row = $(this);
if (filter == "") {
row.show();
}
else {
var cellText = $(row.find(("td:eq(" + index + ")"))).text();
if (cellText.indexOf(filter) == -1) {
row.hide();
}
else {
row.show();
}
}
});
Now handle select box:
this.find("tbody:first > tr").each(function() {
var row = $(this);
if (filter == "") {
row.show();
}
else {
var cellText = row.find("td:eq(" + index + ")").find('option:selected').text();
if (cellText == "") {
cellText = $(row.find(("td:eq(" + index + ")"))).text();
}
if (cellText.indexOf(filter) == -1) {
row.hide();
}
else {
row.show();
}
}
});
Now the whole code:
(function($) {
$.fn.filterTable = function(filter, columnname) {
var index = null;
this.find("thead > tr:first > th").each(function(i) {
if ($.trim($(this).text()) == columnname) {
index = i;
return false;
}
});
if (index == null)
throw ("filter columnname: " + columnname + " not found");
this.find("tbody:first > tr").each(function() {
var row = $(this);
if (filter == "") {
row.show();
}
else {
var cellText = row.find("td:eq(" + index + ")").find('option:selected').text();
if (cellText == "") {
cellText = $(row.find(("td:eq(" + index + ")"))).text();
}
if (cellText.indexOf(filter) == -1) {
row.hide();
}
else {
row.show();
}
}
});
return this;
};
})(jQuery);
You can download the file here.
To use it, simply add the following to your <head> section:
<script type='text/javascript' src='jquery.tablefilter.js'></script>
Then when you want to filter the table, just do the following:
$("#your-table-id").filterTable('filter_text', 'column_name');
Thanks for the code.
May I suggest you include the HTML code that the jQuery is suppose to work on next time? Otherwise it might be useless to beginners.