04 Sep

hierarchical select lists

click here for an example

I was working on a large project for the services company in the food industry. It had an interesting problem, where the user must be able to quickly select a single ingredient or recipe out of potentially thousands.

The standard solutions did not fit what I needed, so I came up with an idea: arrange the ingredients in a large select list, which was hierarchical in nature.

<select>
 <optgroup label="general">
  <optgroup label="a to c">
   <option>abalone</option>
   <option>bran</option>
   <option>corn</option>
  </optgroup>
  <optgroup label="d to f">
   <option>dogmeat</option>
...

Unfortunately, the w3c specs do not allow nested optgroups.

The solution, then, was to somehow automatically decide how to partition a large list into sub-lists.

One thought I had was to separate the items by letter and following letters:

aba...
  aback
  abaft
  abandon...
    abandon
    abandoned
    abandoning
    abandonment
    abandons
  abase

This is potentially a very bad solution. If, for example, there were enough ingredients that all 26 letters were available, and the 26th letter had a load of sub-lists, then the entire screen could be covered in this list!

After a while, it became clear that the solution was to ignore the letters, and simply decide on a maximum number of items per sub-list. This would naturally break itself into a number of sub-lists.

When I had initially started on this, it was around last September or so. I ran a search first to see if anyone else had done this (easier to build on someone’s example, sometimes, than to build it all from scratch), but there was nothing like this.

So, I started coding.

All of my javascripts are coded the same way – first, you build your interface as if it’s intended for a non-javascript browser, then you run your script over that code, modifying it as needed. So, I wanted a long drop-down to be available if the end-user did not have javascript enabled.

I gave up on this temporarily, shortly into the project – translating directly from an existing select list to a hierarchical menu style is very confusing!

After a few months, I went back to the code, and started again.

Before trying anything, I ran another search. This time, I came up with this – almost exactly what I was planning!

A quick look at the source showed me that this method required that the browser have javascript enabled. This was a slight disappointment, but not a problem.

Now, instead of translating from a select list to a hierarchical select menu, I just needed to translate from a select list to the data format that Levik’s code used.

I also needed to improve the code so that I could have multiple copies on the same page.

the most difficult part of writing this code was the recursive aspect of it. Javascript’s variable scoping is pitiful, so recursion of any type was a bloody nightmare, but I could not think of any way to do this that did not involve recursion.

Anyway, I persevered, and it’s now done.

I call it hierselect.

example

To use this, simply download the script, create a select list with optgroups for the top-level categorisation, and link to the script. That simple!