Mutual Exclusion with minimal javascript

With toilet cleaner becoming so popular for building web applications (oh c'mon, toilet cleaner — it's not that hard to figure out), it's not at all uncommon to run into a scenario in which you need to make one option, among a list of options, appear to be selected without doing any sort of page refresh or linking to another page.

Often, only one of these options can appear selected at a time, so one might call these options mutually exclusive (see wikipedia for an in-depth explanation of what mutual exclusion means in the world of programming).

Now, there's a good way to accomplish this and there's a bad way; an easy way and a tedious way; an elegant way and an ugly way. And if you're anything like most poeple, you probably tend towards the latter approach.

In this blog entry, I hope to illustrate how to accomplish mutual exclusive link selection (visually) with an astonishingly small amount of Javascript code.

Now, I know my blog entries tend to be a bit long, but I just can't bring myself to explain the technique I'm about to explain without first showing a quick demonstration of how most people attack this problem. I think the contast between the two approaches is really important.

Here's an approach that I consider "the long way around":

function select(_elem)
{
  document.getElementById('music').className = 'unselected';
  document.getElementById('movies').className = 'unselected';
  document.getElementById('books').className = 'unselected';
  document.getElementById('food').className = 'unselected';

  _elem.className = 'selected';

  return false;
}

<a id = "music" href = "#" onclick = "return select(this)">Music</a> |
<a id = "movies" href = "#" onclick = "return select(this)">Movies</a> |
<a id = "books" href = "#" onclick = "return select(this)">Books</a> |
<a id = "food" href = "#" onclick = "return select(this)">Food</a>

If you're wondering about the return false in the javascript function, this was explained in-depth in my blog entry Preventing the Default Action.

The above example is not at all difficult to understand; it's just a total pain in the butt and completely unnecessary. There are various ways you could handle the select(..) function, but in this example, we're unconditionally setting the .className property of all the <a> tags to 'unselected' and then at the end of the function, we set the .className property of the <a> that was passed into the function to 'selected'.

This works of course, but imagine the maintenance nightmare involved here, not to mention how error prone this is. If we add any new options to our list of links, we have to modify the function to account for the new link. A well-written function would not need to be updated when our HTML changes.

The above example can be improved by wrapping the links in a div, using .getElementsByTagName(..) to select all of the child <a> tags and then using a looping technique rather than referencing each individual link element, but I still consider this to be "the long way around."

Now let's look at my personal favorite technique to accomplish the same thing.

Goto page 2 to learn this technique.

Pages: 1 2 3

Got something to say?

Please note: Constructive criticism is welcome. Rude or vulgar comments however, are not and will be removed during moderation.