Checkbox filters with jQuery
Perhaps I'm using delicious.com wrong, but sometimes I wish I had the ability to narrow down my results from a variety of different tags rather than excluding results that don't share the first tag I marked. That's where this exercise came into play.
The technique can be used anywhere. In my line of work (online hotel reservations), I've experimented with this technique for a room selection for online hotel reservations. For instance, hide all but the non-smoking rooms with a king bed, and only show me rooms that I can pay for in advance to get the cheaper price. That sort of thing.
For this article, I'm going to base my examples on delicious.com's bookmarks.
Disclaimer stuff
This isn't so much of a 'teaching' post as it is an 'asking to be taught' post. Despite the danger I can cause, I'm no JavaScript/jQuery guy, and there are plenty of places here that I'm going about this all wrong. In those instances, I need your help. I'll call out some specific questions where I know I need improvement. And if you see additional places, please let me know. In the meantime, don't look to this post as tried-and-true, ready-to-copy-and-paste way to do things, because it's far from it.
The HTML
Let's recreate a delicious bookmark listing and leave out the filters for now. Here's the html for a single listing:
<ul>
...
<li>
<h4>The Power of WordPress and jQuery: 25+ Useful Plugins & Tutorials</h4>
<p class="url">http://www.noupe.com/jquery/the-power-of-wordpress-and-jquery-30-useful-plugins-tutorials.html</p>
<p class="tags"><strong>Tags:</strong> plugin, wordpress, webdesign, jquery</p>
</li>
...
</ul>
In order for this to work, we need a way to get the list items using class names. So the tags are repeated as class names. Also, I'm going to give this particular list a class name so the javascript has something to target later.
<ul class="filterThis">
...
<li class="plugin wordpress webdesign jquery">
<h4>The Power of WordPress and jQuery: 25+ Useful Plugins & Tutorials</h4>
<p class="url">http://www.noupe.com/jquery/the-power-of-wordpress-and-jquery-30-useful-plugins-tutorials.html</p>
<p class="tags"><strong>Tags:</strong> plugin, wordpress, webdesign, jquery</p>
</li>
...
</ul>
We create several of these records and we have ourselves a nice delicious-like page of results.
View example 1 - the starting point: basic page, no javascript
Let's say it in English
The JavaScript for this is kind of long and boring, not to mention that I'm not doing it right in several places. So instead of reprinting it, I'd rather just say in English what I wanted the JavaScript to do. Writing out the logic in English is always a good practice anyway. So here goes:
When the page loads, look through all the class names of the list items to be filtered, and build a new list with all the unique values of those class names, along with a corresponding checkbox. Being friendly, we'll also include a 'show all' checkbox at the end of the list. Since all items are shown by default, all checkboxes will be shown by default, too. When someone unchecks a box, hide any item that has the class name of that checkbox's value. When rechecked, show any item that has the class name of that checkbox's value.
Mouthful, right? There's much more to come, as I quickly realized that there is more I needed to do with this list.
View example 2 - the starting point: basic page, no javascript
Working through one issue at a time
Issues I immediately noticed with example 2:
- 'jquery' is a common tag to every item. How should that be handled?
- When i uncheck 'webdev', an item that has the class of 'resources' also disappears. It's the only item with the class of 'resources', yet it's checkbox stays checked, misleading me into thinking that because it's checked, there must be a listing showing that has it.
- It would be nice to alphabetize the filters.
The latter one was the easiest to knock out. I can sort the array of unique class names by adding this line to the JavaScript:
arrayUniqueClasses = arrayUniqueClasses.sort();
Also, I chose to exclude any class that is common to all elements from being in the filter column. (My code is probably cruddy for doing this - would love feedback on this.) For sake of demonstration, I created a paragraph above the filters that states which classes those are common to all list items.
View example 3 - alphabetized filters, and excluding tags common to all list items.
I noticed an additional challenges:
- When a filter is unchecked, before hiding the list item, I need to check other classes on the list item to be hidden.
- When a filter is checked again, in addition to showing the list item, I need to check all the other filters for every other class associated with a newly shown list item.
- For my personal preference, I wanted to add this in: If all other filters are checked, go ahead and recheck the 'show all' checkbox.
To see how I tackled these challenges, I recommend viewing source on the examples. The script is commented with what I'm doing and questions to myself throughout the process.
Questions for people with more jQuery/JavaScript experience than me:
- In order to have only unique values in my array, I'm using a function called
unique(a)(credit: Johan Känngård, http://johankanngard.net/). I tried to use jQuery.unique, but it wasn't working right. If anyone can do the unique part in jQuery for me and point out how it's done, I'd be much appreciative. - I'm using what is probably an unreliable method for determining if a tag is common to every result. I count the number of list items, and I count the number of times any class appears. If a class's total occurrences equals the total of all list items, I assume that class is common to all list items. Is there a better way to do this?
- I'm removing items from my arrays using a
removeItems(array, item)function that I got from who-knows-where. Is there a way I can do this in jQuery? - Any other things that could be done better?

Comments (15)
Anonymous said:
hey, that's pretty nice. I'd love to see that on the jQuery site. No problems during a quick drive in FF3.
# March 10, 2009 3:48 PM
T said:
Nice post!
# April 1, 2009 7:37 AM
Amy Wake said:
Love your posts. Glad to see more jQuery posts apearing on your blog (event though you say you are not a jQuery guy :)). I case across post while searching for checkbox manipulation and checking if checkboxes are checked, so I thought I would share this related "jQuery checkbox" post with other users. Hope you will find it useful.
# May 13, 2009 7:29 AM
Trever said:
This comment could be bestowed on a myriad of your articles. I'm inspired by your thoughtful, and informative posts. Mr CSS Guy, thank You for your hard work!
# May 29, 2009 3:07 PM
Cynthia said:
Hi, great post! Can this be integrated with Wordpress? I'm trying to find a way to filter results (based on Wordpress posts I tag with certain words), but no luck finding a Wordpress plugin that will do it.
If you have any advice or can direct me to another site with something similar, that'd be wonderful. Thanks!
# June 21, 2009 8:36 PM
Benjamin said:
You know that you don't need the markup to assign classes to each div. You could use jQuery to loop through, and add those classes automatically, based on the content from the ...
I think the reason jQuery.unique doesn't work is its supposed to work on DOM elements only, and not arrays of strings.
# July 4, 2009 7:26 AM
Tony said:
I'm using this on my upcoming portfolio and it works great, really great.
I changed it so that instead of sliding out the list element fade out, that was easy.
I was wondering though if there is a way to make an image residing inside the "li" element to fade out when you check off that particular tag instead of fading out the whole "li"?
I hope you know what I mean, and thanks for any help you can provide.
Lastly, I would like to style my checkboxes with this. Styling works fine, but nothing happens when I check/check off the boxes, any ideas there?
Anyhow, great job on the filtering script :)
# August 13, 2009 7:28 AM
pritaeas said:
Thanks for your great example. I made this with it, after some revision: http://www.pritaeas.net/tools/linkfarm/
# November 1, 2009 1:06 PM
Alex said:
This is a great piece of code! I'm using it to filter out the results on my results page, but in the case of the search result only being '1' I'd like to hide the check-boxes and "Classes excluded from filters because they are common to all elements:" phrase.
I can accomplish this with an if-statement in the javascript, but how would I phrase it? What would be the (condition)?
if (condition)
{
code to be executed if condition is true
}
Thank you so much!
# November 30, 2009 2:18 PM
CSS Guy said:
@Alex:
Great question. I certainly didn't account for what happens when only one result is listed.
I'd add this as the first line after the $(document).ready(function () { part:
if ($('.filterThis > li').length < 2) { return; }This checks to see if the number of results is less than 2 (such as one or none), and if so, just escape out of the loop. This way, no checkboxes would be created and no sentence regarding excluded filters would be created either. Does that help?
# November 30, 2009 9:37 PM
Jesse said:
I am using your script to filter my online portfolio. I have four tags set up (logo, website, marketing, print). Lets say an li has a class of "website logo" (two tags). When I uncheck logo I still want that element to remain (not disappear) because it still has a tag of website (which is still checked). I basically want to set your script so an element only disappears if all the tags are unchecked, not just one. How can I do that?
# December 3, 2009 7:05 PM
CSS Guy said:
@Jesse,
I think I know what you mean. Does this example help?
Jesse portfolio filters
# December 4, 2009 1:31 PM
Ross said:
Any ideas as to how to slow down the transition?
also as Tony mentioned how to implement a fade?
Still tho, Fantastic code, thanks
# February 16, 2010 5:39 PM
Bryan Chalker said:
Hey CSS Guy...this script is awesome - and perfect for what I need (filtering a/v files based on tags) - but some tags will be multiple words with spaces in between ("man's role", "financial stability", etc.). How do I set this up to use a comma rather than a space between classes? Also, can it be an "attr" rather than class? Thanks
# March 11, 2010 10:36 AM
CSS Guy said:
@Bryan,
Great question. I didn't accommodate for tags that have spaces in them.
I'm not sure I can help. I viewed source on my final example and even though I wrote the code, it made my eyes roll into the back of my head. I wish I had time to make this more flexible, but without sitting down to do it again from scratch, I'm not sure I can.
Sorry I couldn't help further. If you figure something out, send it over and post a comment. I'd be more than happy to link to what you've got.
# March 11, 2010 10:50 AM