Live ListSelect Filtering with Javascript

{{7/16/2015 Workflow 7.6 update — review this update for new info on this post.}}

For a project I’m developing that involves interactive reports, I needed the ability to filter results based on user input.  I didn’t want to do the usual – type a value into a TextBox, click a “filter” or “search” Button and then have Workflow run a filter and reload the entire form with the new result set.

With the help of Google and a number of great reference articles, I was able to piece together a bit of Javascript that results in a very slick and seamless ListSelect filter.

listfilter

The good news is that the list index remains intact, so clicking a list item passes the appropriate data downstream in the Workflow process.

One unfortunate caveat, however, is that the alternating row colors didn’t play nicely with the filtered out rows.  Basically, the rows that were white stayed white even post-filtering, and vice versa.  So I had to break one of my personal rules and use Javascript to set inline styles dynamically as the filtering is processed in order to re-draw the alternating row colors.

So let’s start with the CSS for the demo package.


/***Lists***/
/***.gaListSelect***/
.gaListSelect td {
 font-family: Verdana, Serif;
}
.gaListSelect:focus {
 outline: none;
}
.gaListSelect table {
 width: 100%;
 border-collapse: collapse;
}
.gaListSelect tr td a {
 width: 100%;
 height: 100%;
 display: block;
}
.gaListSelect > table > tbody > tr:nth-child(odd) {
 background-color: #eff4f7;
}
.gaListSelect > table > tbody > tr:hover {
 background-color: #cccccc;
 -moz-transition: background-color 200ms ease-in-out;
 -webkit-transition: background-color 200ms ease-in-out;
 -o-transition: background-color 200ms ease-in-out;
 transition: background-color 200ms ease-in-out;
}
.gaListSelect > table > tbody > tr > td > a {
 color: #999999;
 text-decoration: none;
}
.gaListSelect > table > tbody > tr:hover > td > a {
 color: #ffffff;
 -moz-transition: background-color 200ms ease-in-out;
 -webkit-transition: background-color 200ms ease-in-out;
 -o-transition: background-color 200ms ease-in-out;
 transition: background-color 200ms ease-in-out;
}

/***Input***/
input {
outline: none;
}
input[type="text"] {
 border: none !important;
 box-shadow: inset 0 1px 2px rgba(0,0,0,.2),inset 0 -1px 0 rgba(0,0,0,.05);
}
.gaInput {
 font-size: 16px;
 font-family: Verdana, Serif;
 padding-left: 6px;
 padding-bottom: 2px;
 background-color: #f7f7f7;
 color: #999999;
 -webkit-appearance: none;
 border-radius: 0;
}
.gaInput:focus {
 background-color: #ffffff !important;
 color: #525252 !important;
 outline: none;
}

This will handle the styles for the 2 interactive elements in our demo, the ListSelect and the TextBox.

Next, the Body onload event:


var testList = document.getElementById('TestList');
var testTable = testList.firstElementChild;
testTable.setAttribute('id','TestTable');
var testFilter = document.getElementById('TestFilter');
testFilter.setAttribute('oninput','filter("TestFilter", "TestTable")');

When setting a Control Id for the ListSelect component, the Id is set for a wrapper element.  This javascript sets a control id for the actual “table” tag of our ListSelect component so that we can use a table function for the filter.  This code also adds an oninput function so that as we type, the function runs the filter for us.

Here’s the filter function for the Script section of our form.



 function filter (textBoxId, tableId){
var testFilter = document.getElementById(textBoxId);
 var suche = testFilter.value.toLowerCase();
 var table = document.getElementById(tableId);
 var ele;
 var c = 0;
 for (var i = 0; i < table.rows.length; i++){
 ele = table.rows[i].innerHTML.replace(/<[^>]+>/g,"");
 if (ele.toLowerCase().indexOf(suche)>=0 ) {
 table.rows[i].style.display = '';
 var c = c + 1;
 if (c%2 == 0) {
 table.rows[i].style.backgroundColor = '#ffffff';
 } else {
 table.rows[i].style.backgroundColor = '#eff4f7';
 }
 } else { 
 table.rows[i].style.display = 'none';
 }
 }
} 

Basically this function takes our TextBox input as we type, and compares that value to each row in the table.  If a substring match is found, the row is kept.  If not, it’s set to not be displayed.   A second “if, else” evaluation is used along with a counter to determine the new alternating row styles.

Now in order to properly leverage the javascripts, we need to set the form up properly.  In the demo package, the ListSelect component is given a Control Id of “TestList” and the TextBox component “TestFilter”.  An IncludeHTML component is used on the form to apply our CSS.

The end result is a decent start for a usable list filter.

A demo package is available on the Demo page.


Featured Components

ListSelect

TextBox

IncludeHTML


Further Reading

CSS and Workflow

Javascript and Workflow


One thought on “Live ListSelect Filtering with Javascript

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