A quick & dirty write-up for a new (and terribly beta) script. I’ll spend some time writing something more coherent next week… I suggest you take a look at the hastily produced demo before you read any further.
Integrating the filter into the table
There are two ways in which to attach the filter to a table, “embedded“, in which the script creates and adds a new row to the table or “popup“, in which a link is added to the required table headers that show the popup filter when pressed.
The embedded filter
The embedded filter is integrated directly into your table structure. The script will create a new table row (TR) and populate this row with cells (TH), each containing a form and, depending on the type of input method requested for the associated column, either a text input or dropdown list.
As the script creates a new form within each table cell, this method is not compatible with tables that have already been wrapped by a form element.
The Popup filter
This option creates a link within each required table header (TH) which displays the popup filter when pressed. To stipulate that a table should use a popup filter, just add the class popup-filter to the associated table’s className.
Popup filter HTML
The following HTML is created by the script and added to the end of the current document should a popup filter be used:
<div id="fdTablefilterWrapper">
<form ... >
<p><input ... id="fdFilterInp" /></p>
<p><select ... id="fdFilterSel"> ... </select></p>
</form>
<div id="fdtl"></div>
<div id="fdtr"></div>
<div id="fdbl"></div>
<div id="fdbr"></div>
<div id="fdlb"></div>
<div id="fdrb"></div>
<div id="fdbb"></div>
<div id="fdtb"></div>
<div id="fddongle"></div>
</div>
This gives you lots of styling hooks should you wish to restyle the popup filter to better suit your application’s look & feel.
Additionally, a link is added as the first child of each column to filter. This link wrap’s an image whose source is set to be a 1px x 1px transparent gif (that should reside in the same location as the filter script). This enables you to style the “button” states by using only CSS e.g. by changing the background property of the img.
<a href="#" class="fdFilterTrigger">
<img src="/the/path/to/the/filter/script/blank.gif" alt="" />
</a>
Have a look at the generic CSS and Internet Explorer specific CSS (integrated using conditional comments) used within the demo in order to see how the button was styled.
Filter Input mechanisms
There are currently two ways in which to input search terms; a text input and a dropdown list.
The dropdown list
The dropdown list is populated by a sorted list of all the unique cell data parsed from the associated column. To stipulate that a column should use a dropdown list, just add the class create-list to the associated TH node’s className.
The text input
The text input enables users to filter the column using bespoke search terms. Additionally, comparison operators can be also be used to strengthen the search term (”>”, “<", ">=”, “<=”, “!” and “=”).
Column Datatypes
It is necessary to indicate to the script the type of data contained within the column. This is done by adding a class of the format datatype-X to the associated TH node, where X is replaced by the name of the column’s datatype.
The script can currently parse dates (dd-mm-yyyy, mm-dd-yyyy or yyyy-mm-dd formats accepted), currency values (£, $, €, ¥ and ¤), numbers/floats and finally, plain-text. Additionally, the character used as the date divider (i.e. the character that separates the date parts) can be “/”, “-”, “.” or “ “ (space).
The Numeric datatype
Adding the className datatype-numeric to the associated TH node will instruct the script to attempt to parse numeric data from the column’s cells.
The numeric parser bundled with the source code is quite ruthless with the data passed to it. It will replace any character not valid for use within a floating point number and then attempt to parse a float from the result.
This means that the script can be used to filter all manner of numeric column data, for example; columns containing percentages e.g. -22%, 34.6% etc do not require a bespoke parser in order to be filtered – giving the column the className datatype-numeric will suffice.
The Date datatype
The script currently favours the American date format of “mm-dd-yyyy”. This is the first format that all dates are tested against during the data preparation phase, which means that European dates such as 10-08-2006 (i.e. the 10th August 2006) will be parsed as the 8th October 2006.
Should your dates be of the European format “dd-mm-yyyy”, add the class datatype-datedmy to the TH node instead of the class datatype-date, this will tell the script to attempt to parse a DMY format date before attempting to parse a MDY format date.
Plain-text data
If the column contains plain text, just give the associated TH node the className datatype-text.
Bespoke datatypes
Should the data within the column require a bespoke parser, just add a className of the form datatype-X to the associated TH node, where X is replaced by the name of a function the script will attempt to use when preparing the column data; for example, giving the TH node the className datatype-dutchCurrency will instruct the script to call a Javascript function named dutchCurrency in order to parse the cell data.
An example function is shown below:
// A bespoke cell data parser that parses the dutch currency
// format e.g. $100.000,00
function dutchCurrency(tdNode, innerText) {
innerText = parseFloat(innerText.replace(/[^0-9\.,]+/g, "").replace(/\./g,"").replace(",","."));
return innerText;
}
Zebra striping the table rows
Should the table be given the class rowstyle-something, each alternate table row is given the class something after the table has been filtered i.e giving the table a class of rowstyle-alternate will tell the script to give each alternate row the class alternate.
Hiding the filtered table rows
Whenever a table row is hidden by the filter script, it is given the className invisibleRow. This class should be defined within the CSS as shown below:
.invisibleRow {
display:none;
visibility:hidden;
}
Please note: It is necessary to include both the display and visibility properties within the class definition in order to truly hide the row from certain screen-readers.
Clearing all the current filters
To clear all the current filters for a table (i.e. reset the table), you must call the method fdTableFilter.clearFilter(theTableId), passing in the ID of the table to be reset.
Filter Commands
The text input filter enables you to enter math-like commands to assist when filtering. A rundown of the commands is listed below:
| Command | Explanation | Example |
|---|---|---|
| > | Show only cells that contain data greater than the search term | > abcd |
| >= | Show only cells that contain data greater than or equal to the search term | >= 1970 |
| < | Show only cells that contain data smaller than the search term | < 13/03/1970 |
| <= | Show only cells that contain data smaller than or equal to the search term | <= abcd |
| = | Show only cells whose data matches the search term | = 01/03/1987 |
| ! | Show only cells whose data does not match the search term | ! abcd |
Integrating the filter into your HTML.
Just link the script in the HEAD of your (X)HTML document and give the table and TH nodes the required classNames.
Demo, downloads and updates
Tested in Internet Explorer 6 & 7, Opera 9.01, Safari 3.1 (Windows) and Firefox 2.
View the table filter demo.
04/04/2008 (v1.2):
- Added the “clearFilter” method
03/04/2008 (v1.1):
- The embedded filter can now be used within tables that have no THEAD
07/01/2008 (v1.0):
- First release

Previous Comments ~
Keep getting error:
Index or size is negative or greater than the allowed amount” code: “1
Line 0
@ Jim: Hi Jim, as I say, it’s “terribly beta”... what browser are you using? Can you post a link to the page in question?
Thanks,
Brian
Both in FF and IE.
Best I can get is line 844, fdTableFilter.fdScriptFiles[...].src is null or not an object.
That is from IE.
FF errror only shows Index or size is negative or greater than the allowed amount” code: “1.
HTH
D%&m your stuff is good!
I am just getting my grid to paginate and sort. Wanted to add a search or filter of some sort (no pun intended). Have 925 records and sorting is
http://wholesale.sigels.com/content/view/13/12/Libby-glassware.html
1st and foremost..Superb Job FD!!!
2 Inquiries
1st: Is there a way to reset (or filter) the table to show/unhide all rows? Right now, if you give focus to an empty text-input filter and hit enter on the keyboard, the table will reset and show all hidden rows. I want to make it a tad clearer to the users that they can accomplish this (resetting the table that is). Much in the same way you have allowed us to sort column data using external javascript buttons.
I figured this would be handled by the filter.js as opposed to the sort.js. Is there a method/function you have already built -in the javascript that can be called to accomplish this…if not how would I go about creating one? Or would it be a combination of the JS and CSS...perhaps an .invisibleRow equivalent :
tr.showallRows { display:inline; visibility:visible; }
———————
2nd – Is there also a way to pre-populate text-inputs (and maybe even the drop down boxes) with a value. Say…like the word “filter,” so again it is clear to users that row under the table header is used to filter column data. Of course this value of would not have to be an actual column value. Its just for clarity in directing the flock. I am using the embedded filter if that isn’t obvious at this point.
Many thanks in advance…Also can I get a pint of Cherry Kool-Aid in the virtual keg, I a little wet behind the ears. :o)
@ Jim: hi Jim, in fact, I broke the first rule of web development and assumed that people would be including the script within the head of the HTML document (never, ever assume!). To remove the error, just change the line (located at the end of the file):
fdTableFilter.fdScriptFiles = document.getElementsByTagName(“head”)[0].getElementsByTagName(‘script’);
to:
fdTableFilter.fdScriptFiles = document.getElementsByTagName(‘script’);
@ Ty Nichols: Hi Ty, in fact, that’s two things I didn’t think about when writing the script. I’ll try to integrate the functionality into a new version this week.
Thanks for the input guys, much appreciated.
Regards,
Brian.
Now I get an error:
illegal character
http://wholesale.sigels.com/modules/mod_dbdisplay_ext/js/tablefilter.js
Line 842
fdTableFilter.fdScriptFiles = document.getElementsByTagName(‘script’);\n
But there is no newline there??
BTW – this is in a module inside the Joomla CMS so there is a lot going on. But I have no idea where the error of a newline is coming from.
Thanks so much.
J.
@ Jim: Hi Jim, I’m guessing that you copy/pasted the corrected line from the comment itself. This means that the quote character has been textiled (and turned into a more typographically correct curly quote character) – try changing the curly quotes to straight quotes and it should work.
no joy<sigh>
still same error. Must have to do with something in the page itself that it is picking up. I’ll try to get to it today and look – have to work on getting the rest of the grid and lightbox working. Thanks so much…
I just modified the line in the js itself. (forgot the document. the first time).
Working within the framework can be a little challenging because the operating system (Joomla) has so much going on and we can’t always get the stuff in the header but I’ll try that next. When i get this running I’d like to talk to you about incorporating this into the Joomla components and modules for others in the OS CMS to use. This is a great set of grid functions, and fast too.
Put everything in the header, now get following error:
tbl.getElementsByTagName(“thead”)[0] has no properties
http://wholesale.sigels.com/modules/mod_dbdisplay_ext/js/tablefilter.js
Line 265
Thanks
J.
I love your scripts.
I have used the tablesort script for a while now. I had to do a lot of “hacking” to get it to handle the data. I had to build a datetime sort function because the built in date function didn’t handle any javascript. i.e. anything that came be passed to the Date() function. As well, if I didn’t specify a datatype on the th and the data had characters like ‘$’ or ‘%’ it defaulted to sorting it as text.
Will I need to modify this filter script in a similar manner or will the modifications made to the tablesort also work with the filter script.
@ Jim: Hi Jim, your table doesn’t have a thead (which the script requires at this early iteration). I’ve fixed it for the next version (which I’ll try to upload today).
@ Jonathan: Hi Jonathan, you shouldn’t need to hack the script at all as you can extend it with custom sort functions. As for the text sorting, as the “%” and “$” characters aren’t part of a valid date, the script defaults to the text sort.
Basically, all you need to do is write a custom sort function (that can most probably be used for both scripts). There’s lots of custom sort examples to base your verson on.
Brian,
I had another epiphany about the filter table around 4am yesterday morning that may enhance its functionality and all around “bad-assness.” Is there a way to consilidate the drop-down list values so that multiple instances of equivalent values in a column appear only once?
An example (embedded filter table):
If I have a column that utilizes a drop-down list and has the following values [Cheese | Meat | Pickle | Cheese]
Is there way to consolidate those values in the drop down list so that when a user clicks the drop down list for that column it displays [Cheese | Meat | Pickle] , as opposed to [Cheese | Meat | Pickle | Cheese], despite the fact that there are actually 2 [Cheese] values displayed in that column?
I am proposing this because the column I am using has potentially hundreds of rows that share the same value for the column in question. Which means the drop down list for said column is displaying:
[Cheese] x (1 gazillion) in the drop down-list
Which is just a waste of virtual ink in my opinion.
I hope this all makes sense…
In Awe,
Ty
PS – Any luck adding reset functionality?
@ Ty: Hi Ty, in fact, the script already calculates a unique data set like that – as for the reset, I wanted to do it this afternoon but a rather large bug has been found in an internal application and I have to fix it today so (most probably), I won’t get the time to work on the reset code…
@ Ty: Hi again Ty, well, the bug was a sinch to fix and so I had time to write the clearFilter method.
Regards,
Brian
@ Ty: Hi again Ty, well, the bug was a sinch to fix and so I had time to write the clearFilter method.
Regards,
Brian
Ahhhh Brian!!! You are correct, it does calculate a unique data set. The reason I was thrown off was because my table’s column contains genres of music (no, not hamburger accessories). So values with special characters ( – , & , etc.) are not “valid” for the calculation. So my “R&B” and “Hip-Hop” string values are not being parsed correctly. My apologies, a simple look at the drop-down list and comparison to my column data would have yielded this earlier, before my cheesy and voidable post. I owe you a virtual pint. No worries, I will just not use any special characters.
Great job on fixing your bug quickly and generating the clearFilter method!!! Exactly what I needed.
Implicitly Impressed,
Ty
Awesome, excellent work!
I’m trying to incorporate the filter script via drop downs and checkboxes outside of the table. The checkboxes are ‘hardwired with filter options for pre-targeted columns. I’m having trouble integrating that method with your solution. Can you give an example of a static, ‘only show this’, filter? Can the dropdowns exist outside of the table?
@ Geordie: Hi Geordie, I’d need to see your code to see exactly what your trying to do with the “hardwired” filter. Unfortunately, this version of the script will only create the dropDowns within the table.
Hello,
well, I was trying to figure out how to use your ‘simulated filter’ example, since it exists in its own form. Essentially, using that form as an example, lets say you wanted to filter out ‘Batman Begins’ from column Movie, and ‘Batman Begins’ is either the name or value of a form’s checkbox and when I click the submit button, the filter would be applied.
Can that be achieved? I don’t want to clog up your comment list with a bunch of code.
Thanks so much!
Hi,
I have to congratulate you on such a wonderful script; does what it says on the tin. Also, the table sorter script is also another work of art; truly fantastic.
You have saved me many hours of typing and frustration with this script.
I am struggling to get it working on one of my pages where the form needs to have a “name” attribute in. This is only happening in IE6 (suprise, suprise). I believe it is causing the script to not work properly (as I don’t get the filter input boxes being written into the page along with a JS error). It does work in Firefox though.
Any idea how I can modify the script to work with a form with a “name” attribute in in IE6?
Thanks in advance.
PS – I have also left out any code here so as not to clog up the page but I can provide it if it helps. To recreate the issue, take a working page and give the form a valid “name” attribute.
hello
very nice script, but i need to put one last row “totals” based on the filtered “numeric” columns. any ideas ?
@ Gordie: Hi Gordie, it should be possible by using a bespoke parser (check out the demo parser within the article). Parsers are passed the actual TD node as an argument so you could just return the checkbox value e.g. tdNode.getElementsByTagName(“input”)[0].value
@ ADPD: Hi ADPD, have you given the form an ID attribute that is different than the name attribute? i.e. id=“hello” name=“world”
@ Peter: Hi Peter, the script currently doesn’t include post-filter callback functionality – something I’ll have to integrate into the next version. This would allow you to scan the table for visible rows and calculate the total correctly.
First of all, these lab scripts of yours are excellent. Very polished and complete.
I’m attempting to build a user script which will allow the user to sort/filter any data table on any Web page using your Table Sort and Table Filter scripts. It’s pretty functional at the moment, but I’m having some trouble with the default embedded filter method. After entering a value to sort by and pressing enter, it just refreshes the page rather than actually sorting, leading me to believe it’s some king of issue with preventing the default form action. Oddly enough, when I use the popup filter input, it works fine. I’ve tried to debug the problem, but there’s a lot of code to look through. Any light you could cast on the problem would be great.
@ Dylan: Hi Dylan, can you send me a link to the page in question? Thanks – frequency.decoder at google’s email app…
Quote: @ ADPD: Hi ADPD, have you given the form an ID attribute that is different than the name attribute? i.e. id=“hello” name=“world”
Yes; your comment prompted me to revisit the code.
The name I was using for the form was “f”. It disliked this single letter as the form name. Changing it to something longer (e.g. “ff”) seems to solve the issue.
I will dig around to see why this is the case (as the name=“f” was unique, only appearing once in the code).
Thanks for taking the time to support such a wonderful piece of code.
Hi,
I have a table (id=“resultsTable”) inside an iframe (id=“iframe1” name=“iframe1”) on my site. The filter is working beautifully on this table.
I’d like to know if I could have the “Clear All Filters” button in the parent document, working on the table inside the iframe.
I have hacked around a bit, all to no avail.
Any ideas would be greatly appreciated.
I think what I was trying to do was simple; I just had some other JavaScript interfering with it.
The code I have used is as such:
Clear Filters
Obviously, substitute FRAME-NAME for the name of your frame, and TABLE-ID for your table ID.
A final thanks for such a tremendous piece of code; it has added so much value to the application I have integrated it into.