Intelligent Select Box Filtering

Published July 16, 2010 by Rob Glazebrook.

One of the great things about building websites for a living is the challenges tend to change from day to day. There’s always a new puzzle to solve.

Take today, for example. I was building a page that contained a series of select (dropdown) boxes. Now, I’ve been around the block once or twice before, and this wasn’t my first time using selects. However, this implementation came with a unique twist: all the boxes contained the exact same options, but we only wanted each to be selectable once. Specifically, each box contained a list of security questions — your mom’s best friend’s grandmother’s maiden name, that sort of thing.

The code looks something like this:

<select class="security" name="security1">
	<option value="0">Select a question.</option>
	<option value="1">Who's your daddy?</option>
	<option value="2">What's your favorite color?</option>
	<option value="3">What time is it?</option>
</select>
<select class="security" name="security2">
	<option value="0">Select a question.</option>
	<option value="1">Who's your daddy?</option>
	<option value="2">What's your favorite color?</option>
	<option value="3">What time is it?</option>
</select>

Now, naturally, we want the user to select several different security questions. But what’s to stop them from selecting the same question several times? Well, in our case, back-end validation… but I wanted to solve the problem before we got to that point. I wanted to eliminate “selected” questions from all the other dropdown boxes, so it wouldn’t even be an option. This has the added benefit of shortening the list of options as the user goes along, which would make scanning the options easier.

After a bit of playing, I came up with the following jQuery script which seems to do the trick:

$(function () {
  $('.security').change(function () {
    $('.security option').show(0);
    $('.security option:selected').each(function () {
      oIndex = $(this).index();
      if (oIndex > 0) {
        $('.security').each(function () {
          $(this).children('option').eq(oIndex).not(':selected').hide(0);
        });
      }
    });
  });
  $('.security').change();
});

I’ll walk you through what I’m doing here.

First, we’re setting the script to fire whenever the “security” select boxes are changed. In other words, whenever someone makes a new selection in one of our dropdowns.

When a selection is made, the first thing we do is re-display any previously hidden options, to put us back on even footing. Then we loop through each of the selected options in our select boxes. If the first item isn’t selected, we’ll proceed. (In our use-case, the first option was a generic “make a selection” option, so I didn’t want it to count as a question).

Once we know a true question has been selected, we’ll loop through all our select boxes. We’re making heavy use of the jQuery .index() and .eq() functions here. Both functions use the idea of zero-based array indexing to number all of our elements; the fifth option in a dropdown would have an index of 4, the third dropdown with a class of “security” would have an index of 2, and so on. The .index() function lets us grab the index number of any item we already have, and the .eq() function lets us specify which new element we want to grab.

So first up, we grab the index value of the currently selected option. Since all of our questions are in the same order in each dropdown, those questions have the same indexes across the board. Then we loop through each of our select boxes. If the option is not currently selected in that dropdown, we hide it – in other words, the only dropdown that will still contain that question is the one in which it was already selected.

And then, at the very end, we fire our change function. The first time our page loads, that won’t do much. But if anyone refreshes the browser window, the browser will save their select options… which means we need to filter them right when the page loads. Otherwise, all of our questions would be visible again whenever the page reloaded.

I put together a demo here. Take a look!

13 Responses

  1. AJ

    Wow, its been a while since I received an email update from you. Not much CSS going on here, but a very useful post nonetheless. :)

  2. Pingback: 2 Select boxes filter | BlogoSfera

  3. martin

    I used that tech for my system documentatiomn http://jb-webs.com/websiteBuilder-Docs.html it’s cool because by that I could place 400 Videaos on 500 Pages, by keeping whole documentation easy to read – nice side aspect is that I made it by drag and drop, because with my jb website buuilder I can amange even php and not only html5 applications with drag and drop

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>