Latest version is v1.0e
Demo
Background
A while ago, I was working on a typical web application that allows a user to browse and manage customer data stored in a database, among other things. The normal thing to do would be implement such logic on the server-side. However, a specific requirement was that the user must be able to quickly search and find one or more records from a table using one or more search criteria. To make a round trip to the server and back is considered too expensive. Therefore a client-side solution is required.
This solution uses a combination of JavaScript and DHTML. The script was created with flexibility, reusability and simplicity in mind. I.e. The developer (meaning you) is only required to include the script, setup a few parameters, and make the JavaScript calls in the appropriate event handlers.
Features
This script offers the following set of features:
- search criteria can be a text box, single or multi-select list box
- allows a combination of search criteria (as an AND operation)
- 4 types of matching strategies are available:
substring1 - substring search (from 1st char) (default)
e.g. man will match "manhood" and "man is evil" NOT "superman" and "he is a man"
substring - substring search (anywhere within)
e.g. man will match "manhood" and "superman" and "he is a man"
full - full string search
e.g. man will match "man" NOT "manhood", "superman", "man is evil" and "he is a man"
item - search for a word/phrase in a comma separated string
e.g. man will match "man,woman,child" NOT "superman,superwoman,kid" and "boy,girl,dog"
- performs full string match (in
substring1 mode) if last char in search string is a white space.
- allows search to be turned off/on.
- *NEW* allows filtering by checkbox status in the table. Search criteria can be expressed as either a checkbox or a single select dropdown list.
Usage
In order to use this script, you will first have to include it in your HTML as follows:
<SCRIPT LANGUAGE="JavaScript" SRC="tablefilter.js" TYPE='text/javascript'>
</SCRIPT>
And the recommended place to include this code is in the head section of the HTML.
Setting up the table
First, give the table element a handle using the attribute id or name. This is required so that the script can access the rows within the table using this reference. In the cell elements, include a custom attribute called TF_colKey and give it a label to identify the column. Note that this attribute is only required in those columns that will be searched on. Make sure that all cells in a particular column use the same label. Also note that the label names are "case-insensitive".
An example of how this will look in HTML is shown here:
<table id="dataTable">
<tbody>
<tr>
<td TF_colKey="ckbox"><INPUT type="checkbox"></td>
<td TF_colKey="name">Joe</td>
<td TF_colKey="group">Alpha</td>
<td TF_colKey="salary">400</td>
<td TF_colKey="zone">North,South</td>
<td TF_colKey="status">Off-Site</td>
</tr>
<tr>
<td TF_colKey="name">Celest</td>
<td TF_colKey="group">Beta</td>
<td TF_colKey="salary">5000</td>
<td TF_colKey="zone">North</td>
<td TF_colKey="status">OK</td>
</tr>
</tbody>
</table>
Now that's the easy part done!
Setting up the search form
The search criteria input mechanism is implemented using an HTML form. In order to identify the group of search inputs, it is necessary to give the form element a handle using either the id or name attribute.
<form name="filter" onsubmit="TF_filterTable(dataTable, filter);return false"
onreset="_TF_showAll(dataTable)">
Override onsubmit to call the main script function TF_filterTable(table, form) passing in the handles to the table and form elements. By doing so, the search will be activated when the user hits the Enter key. Since this form does not actually submit to a server, append a return false to cancel the submission.
You may also want to allow the user to easily reset the search form and show all the rows by having onreset call the script function _TF_showAll(table) passing in the handle to the table element.
Using a text input box
Use the following code to implement a text input search field:
<input type="text" TF_colKey="name" TF_searchType="full"
onkeyup="TF_filterTable(dataTable, filter)">
The attribute TF_colKey should reflect the name of the column where this search parameter is applicable. So in the case above, the entry in the textbox will be matched against any cells that has the value "name" in its (the cell's) TF_colKey attribute. Again, this attribute is only necessary for those input fields that will be used in the search process. This is especially useful for building complex query inputs (explained in a later section).
The attribute TF_searchType is optional and it defines the type of matching that will be performed. The available choices are substring1 - substring search from first character (default), substring - substring search anywhere within, full - only matches the full string and item - matches any comma-seperated word/phase. In the example above, we are using full string search.
To activate the search as soon as the user presses a key, override onkeyup to call the main search function TF_filterTable(table, form) passing in the handles to the table and form elements.
Using a selection list input box
Use the following code to implement a selection list input search field:
<select TF_colKey="status" onChange="TF_filterTable(dataTable, filter)">
<option TF_not_used value="">-</option>
<option value="OK">OK</option>
<option value="Off-Site">Off-Site</option>
<option value="On Leave">On Leave</option>
</select>
Again, the attribute TF_colKey should reflect the name of the column where this search parameter is applicable. So in the case above, the entry in the listbox will be matched against any cells that have the value "status" in its (the cell's) TF_colKey attribute.
As with all other search inputs, the optional attribute TF_searchType can be specified in the select element to define an alternative matching strategy.
Note that the value attribute of the option element will be used as the search string, NOT the enclosing text. If a particular option is not meant to be searched on (e.g. a default value in a single select drop down listbox like the first option in the example above), use the custom attribute TF_not_used to exclude it from the search.
To activate the search as soon as a selection is made, override onChange to call the main search function TF_filterTable(table, form) passing in the handles to the table and form elements.
If a multiple selection list is used (by specifying the size attribute in the select element), then the selections are matched in an OR manner. Check out the demo to find out how this works.
Filtering the content of the table based on checkbox state
By popular demand, I've added a new feature that allows the filtering of rows based on the state of checkbox. To use this feature, you can specify the search box in one of two ways; either a checkbox or a dropdown list. In the above demo, I've chosen to use the dropdown list for ease of implementation.
Do note that as three states are required to express the search criteria (i.e. checked, unchecked and off), plus the fact that a HTML checkbox cannot be used in tri-state mode, you will need to implement another control (e.g. checkbox) to enable or disable the search checkbox to fully express the search criteria, which IMHO, looks rather clumsy. In any case, the code fully supports this use case and I've done some preliminary testing so it should work as advertised.
The code to display the dropdown list search criteria is as follows:
<SELECT onchange="TF_filterTable(dataTable, filter)"
TF_colKey="ckbox" TF_searchType="checkbox">
<OPTION value="" selected TF_not_used>-</OPTION>
<OPTION value="true">checked</OPTION>
<OPTION value="false">unchecked</OPTION>
</SELECT>
Again, the attribute TF_colKey should reflect the name of the column where this search parameter is applicable. So in the case above, the entry in the listbox will be matched against any cells that have the value "ckbox" in its (the cell's) TF_colKey attribute.
Note that the use of TF_searchType="checkbox" is 'mandatory' for this code to work. In addition, The option value for checked 'must' be a string with the value "true" and similarly, the option value for unchecked 'must' be a string with the value "false".
For those who are interested, the code to display the checkbox search criteria is as follows:
<INPUT type="checkbox" TF_colKey="ckbox"
onclick="TF_filterTable(dataTable, filter)">
Building complex query inputs
One of the challenges I faced in the project was to build a single search criterion using multiple input fields. E.g. table value is "100 USD" and the inputs are constructed using one text box for the numeric part, and one selection list for the units portion (See demo above for a live example).
At first thought, I had wanted to incorporate this feature directly in the script. But I've yet to find an elegant way to do it; the implementation wasn't robust enough to handle all the combinations plus using it becomes really complicated. Perhaps in a future version. In the meantime however, here's an approach you can use:
Define an intermediate input field that is hidden from view (Use either a hidden input field or set the display style to none). Write a custom function to perform the necessary formatting (e.g. concatenating the values) from the inputs that make up the complex query and place the result in the hidden field. Then in the event handler of the search inputs, make a call to the formatting function before calling the table filtering function. And that's it!
Here's the code snippet that does the complex query in the demo above:
<input type="text" name="salText"
onblur="TF_concat_and_set(salText, salSelect, salHidden);
TF_filterTable(dataTable, filter);">
<select name="salSelect"
onChange="TF_concat_and_set(salText, salSelect, salHidden);
TF_filterTable(dataTable, filter);">
<option value="" TF_not_used>-</option>
<option value=" USD">USD</option>
<option value=" SGD">SGD</option>
<option value=" YEN">YEN</option>
</select>
<input type="hidden" name="salHidden" TF_colKey="salary"
TF_searchType="substring">
Notice that the custom attribute TF_colKey is not defined for both the text and select elements as we do not want them to be included in the search; we define that attribute in the hidden input field instead. The function TF_concat_and_set will perform a concatenation of the two input values and place the result in the hidden input. This utility function is included in the table filter script as a convenience for other users.
Turning the search form on/off
A utility function TF_enableFilter(table, form, checkbox) is provided to easily turn the search feature on or off. In the off state, the table will show all the rows and the search form will be hidden. To enable this feature, use the following code snippet:
<input type="checkbox" checked
onclick="TF_enableFilter(dataTable, filter, this)">
Browser Compatibility
This script and the demo were developed and tested on the IE platform only, since the project did not require Netscape compatibility. It shouldn't be too difficult to make it work on Netscape and I'll probably get round to it when I have the time. I would appreciate any help in this area as well.
Conclusion
Well, that's it folks. It has been good fun developing this script and writing this article. Hope you will enjoy it too! Oh, and I most certainly welcome any feedback, bug reports or suggestions.
Version History
-
19/6/2007 - version 1.0e release
- Added convenience function
TF_check_uncheck_all_rows to help check/uncheck all rows in the table
- Added feature to allow filtering by checkbox status via checkbox
OR single select dropdown list
- Added feature to allow filtering by checkbox status
-
24/8/2001 - version 1.0d release
- Added functions
_TF_get_value and TF_concat_and_set
- Hidden input can now be used as a search field
- Implemented "
substring" search mode
- Improved robustness/flexibility: if a cell
<td> in the table or input <input>/<select> in the search form does not take part in the search (hence does not have the attribute "TF_colKey"), the script will gracefully ignore it. Previously, it would generate a script error
- Reintroduced "
TF_not_used" custom attribute to the option element. I've apparently managed to loose it in the v1.0 pre-release *DUH!*
-
16/8/2001 - version 1.0c release
- Modified
_TF_trimWhitespace to trim the front as well
- Fixed bug in
_TF_filterTable that cause AND search combinations not to work properly
-
9/8/2001 - version 1.0b release
- Added
_TF_showAll function
- Modified
_TF_filterTable to use_TF_shouldShow function.
- Added
TF_searchType attribute to define a search type
- Implemented "
item" search
- Added
_TF_shouldShow function
-
26/7/2001 - version 1.0a release
- Added
_TF_trimWhitespace function
- Modified
_TF_filterTable single condition search to include full pattern search if the last char of the search string is a whitespace
-
14/6/2001 - version 1.0 initial release