|
/****
*
* A set of javascript functions to do row filtering in a table given a
* form containing search parameters.
*
* Compatibility : IE4+
*
* Author : Sidney Chong
* Date : 19/6/2007
* Version : 1.0e
*
*
* Features
* ========
* This script offers the following set of features:
*
* #search criteria can be a text input, hidden input, single or multi-select list input.
* #allows a combination of search criteria (as an AND operation).
* #4 types of matching strategies are available:
* 1) substring1 - substring search (from 1st char) (default)
* eg. man will match "manhood" and "man is evil" NOT "superman" and "he is a man"
* 2) substring - substring search (anywhere within)
* eg. man will match "manhood" and "woman" and "superman" and "he is a man"
* 3) full - full string search
* eg. man will match "man" NOT "manhood", "superman", "man is evil" and "he is a man"
* 4) item - search for a word/phrase in a comma seperated string
* eg. 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 whitespace.
* #allows search to be turned off/on.
* #NEW - allow filtering by checkbox status in the table. search criteria can be expressed as
* either a checkbox or a single select dropdown list.
*
* Usage
* =====
* Give the table and search form a handle (using the attribute id or name).
*
* In the cell elements of the table, include a custom atrribute called
* "TF_colKey" and give it a value to identify the column. Note that you only
* need to do this for columns that will take part in the search.
*
* In the form input elements, include also a custom attribute called
* "TF_colKey" whose value will reference the column on which this search
* parameter is applicable. Again, as in the table, you will only need to do this
* if this input field should take part in the search. Also, an optional custom
* attribute called "TF_searchType" can be specified to use another search strategy
* for a particular field. NOTE: "TF_searchType" _must_ be set to "checkbox" for
* filtering by checkbox status.
*
* In an option tag for a select input, use the custom attribute "TF_not_used"
* to exclude the particular option from the search. (Very useful in drop down
* selection list box)
*
* Call TF_filterTable passing in the handles to the table and form to
* perform the filtering.
*
* NOTE that the value of TF_colKey & TF_searchType are case-insensitive.
*
* ChangeLog cum Version History
* =============================
* 19/6/2007 - version 1.0e release.
* 19/6/2007 - Added convenience function TF_check_uncheck_all_rows to help
* check/uncheck all rows in the table.
* 19/6/2007 - Added feature to allow filtering by checkbox status via checkbox
* OR single select dropdown list.
* 19/6/2007 - Added feature to allow filtering by checkbox status.
* 24/8/2001 - version 1.0d release.
* 23/8/2001 - Added functions _TF_get_value and TF_concat_and_set.
* 23/8/2001 - hidden input can now be used as a search field.
* 22/8/2001 - implemented "substring" search mode.
* 22/8/2001 - improve 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 do not have the attribute "TF_colKey"), the script will
* gracefully ignore it. Previously, it will generate a script error.
* 22/8/2001 - 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.
* 16/8/2001 - modified _TF_trimWhitespace to trim the front as well.
* 16/8/2001 - fixed bug in _TF_filterTable that cause AND search combinations
* not to work properly.
*
* 9/8/2001 - version 1.0b release.
* 8/8/2001 - added _TF_showAll function.
* 8/8/2001 - modified _TF_filterTable to use _TF_shouldShow function.
* 8/8/2001 - added TF_searchType attribute to define a search type.
* 8/8/2001 - implemented "item" search.
* 8/8/2001 - added _TF_shouldShow function.
*
* 26/7/2001 - version 1.0a release.
* 26/7/2001 - added _TF_trimWhitespace function.
* 26/7/2001 - 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.
*
****/
/** PRIVATE FUNCTIONS **/
function _TF_trimWhitespace(txt) {
var strTmp = txt;
//trimming from the front
for (counter=0; counter<strTmp.length; counter++)
if (strTmp.charAt(counter) != " ")
break;
//trimming from the back
strTmp = strTmp.substring(counter,strTmp.length);
counter = strTmp.length - 1;
for (counter; counter>=0; counter--)
if (strTmp.charAt(counter) != " ")
break;
return strTmp.substring(0, counter+1);
}
function _TF_showAll(tb) {
for (i=0;i<tb.rows.length;i++)
{
tb.rows[i].style.display = "";
}
}
function _TF_shouldShow(type, con, cell) {
var toshow=true;
if (type != null) type = type.toLowerCase();
switch (type)
{
case "checkbox": //condition is for checkbox
//so lets find out if the cell contains a checkbox
var aInputs = cell.all.tags("INPUT"); //check for input tags
for (var i=0;i<aInputs.length;i++)
{ //and look for the first checked item
if (aInputs[i].type == "checkbox")
{
toshow = (con.toLowerCase() == (aInputs[i].checked?"true":"false"));
if (toshow) break;
}
}
break
case "item":
var strarray = cell.innerText.split(",");
innershow = false;
for (var ss=0;ss<strarray.length;ss++){
if (con==_TF_trimWhitespace(strarray[ss])){
innershow=true;
break;
}
}
if (innershow == false)
toshow=false;
break
case "full":
if (cell.innerText!=con)
toshow = false;
break
case "substring":
if (cell.innerText.indexOf(con)<0)
toshow = false;
break
default: //is "substring1" search
if (cell.innerText.indexOf(con)!=0) //pattern must start from 1st char
toshow = false;
if (con.charAt(con.length-1) == " ")
{ //last char is a space, so lets do a full search as well
if (_TF_trimWhitespace(con) != cell.innerText)
toshow = false;
else
toshow = true;
}
break
}
return toshow;
}
function _TF_filterTable(tb, conditions) {
//given an array of conditions, lets search the table
for (var i=0;i<tb.rows.length;i++)
{
var show = true;
var rw = tb.rows[i];
for (j=0;j<rw.cells.length;j++)
{
var cl = rw.cells[j];
for (var k=0;k<conditions.length;k++)
{
var colKey = cl.getAttribute("TF_colKey");
if (colKey == null) //attribute not found
continue; //so lets not search on this cell.
if (conditions[k].name.toUpperCase() == colKey.toUpperCase())
{
var tbVal = cl.innerText;
var conVals = conditions[k].value;
if (conditions[k].single) //single value
{
show = _TF_shouldShow(conditions[k].type, conditions[k].value, cl);
} else { //multiple values
for (var l=0;l<conditions[k].value.length;l++)
{
innershow = _TF_shouldShow(conditions[k].type, conditions[k].value[l], cl);
if (innershow == true) break;
}
if (innershow == false)
show = false;
}
}
}
//if any condition has failed, then we stop the matching (due to AND behaviour)
if (show == false)
break;
}
if (show == true)
tb.rows[i].style.display = "";
else
tb.rows[i].style.display = "none";
}
}
/** PUBLIC FUNCTIONS **/
//main function
function TF_filterTable(tb, frm) {
var conditions = new Array();
if (frm.style.display == "none") //filtering is off
return _TF_showAll(tb);
//go thru each type of input elements to figure out the filter conditions
var inputs = frm.tags("INPUT");
for (var i=0;i<inputs.length;i++)
{ //looping thru all INPUT elements
if (inputs[i].getAttribute("TF_colKey") == null) //attribute not found
continue; //we assume that this input field is not for us
switch (inputs[i].type)
{
case "text":
case "hidden":
if(inputs[i].value != "")
{
index = conditions.length;
conditions[index] = new Object;
conditions[index].name = inputs[i].getAttribute("TF_colKey");
conditions[index].type = inputs[i].getAttribute("TF_searchType");
conditions[index].value = inputs[i].value;
conditions[index].single = true;
}
break
case "checkbox":
if(inputs[i].isDisabled == false)
{
index = conditions.length;
conditions[index] = new Object;
conditions[index].name = inputs[i].getAttribute("TF_colKey");
conditions[index].type = "checkbox";
conditions[index].value = inputs[i].checked?"true":"false";
conditions[index].single = true;
}
break
}
}
var inputs = frm.tags("SELECT");
//able to do multiple selection box
for (var i=0;i<inputs.length;i++)
{ //looping thru all SELECT elements
if (inputs[i].getAttribute("TF_colKey") == null) //attribute not found
continue; //we assume that this input field is not for us
var opts = inputs[i].options;
var optsSelected = new Array();
for (intLoop=0; intLoop<opts.length; intLoop++)
{ //looping thru all OPTIONS elements
if (opts[intLoop].selected && (opts[intLoop].getAttribute("TF_not_used") == null))
{
index = optsSelected.length;
optsSelected[index] = opts[intLoop].value;
}
}
if (optsSelected.length > 0) //has selected items
{
index = conditions.length;
conditions[index] = new Object;
conditions[index].name = inputs[i].getAttribute("TF_colKey");
conditions[index].type = inputs[i].getAttribute("TF_searchType");
conditions[index].value = optsSelected;
conditions[index].single = false;
}
}
//ok, now that we have all the conditions, lets do the filtering proper
_TF_filterTable(tb, conditions);
}
function TF_enableFilter(tb, frm, val) {
if (val.checked) //filtering is on
{
frm.style.display = "";
} else { //filtering is off
frm.style.display = "none";
}
//refresh the table
TF_filterTable(tb, frm);
}
function _TF_get_value(input) {
switch (input.type)
{
case "text":
return input.value;
break
case "select-one":
if (input.selectedIndex > -1) //has value
return input.options(input.selectedIndex).value;
else
return "";
break;
}
}
//util function that concat two input fields and set the result in the third
function TF_concat_and_set(salText, salSelect, salHidden) {
var valLeft = _TF_get_value(salText);
var valRight = _TF_get_value(salSelect);
salHidden.value = valLeft + valRight;
}
//util function that helps to check/uncheck rows in a table
function TF_check_uncheck_all_rows(tbl, bState, iColIdx, iRowStart) {
for (var i=iRowStart;i<tbl.rows.length;i++)
{
var aInputs = tbl.rows[i].cells[iColIdx].all.tags("INPUT"); //check for input tags
for (j=0;j<aInputs.length;j++)
{ //and look for the first checked item
if (aInputs[j].type == "checkbox")
{
aInputs[j].checked = bState;
break;
}
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.