Here Ye! Here Ye! From this moment onward, Rob Gravelle's version of the Universally Related Popup Menu(URPM) will henceforth be referred to as the Chained Select Box (CSB), as it is more widely known today. For the uninitiated, chained select boxes are HTML Select elements whose contents change based on the selection of a parent control. These are frequently used for related data such as Country - Province/State - City and Vehicle Manufacturer - Model - Trim Level.
Chained select boxes address a challenge that has fascinated Web developers for over a decade now. My interest in the Universally Related Popup Menu dates back to January of 2001 when I submitted a version to be used within one HTML form. Back then, there was no easy way to represent the data in a JavaScript object, but that was before the emergence of JSON and object literals -- or JavaScript frameworks for that matter.
Things have changed a lot since then, so much so that I thought it about time to revisit the Chained Select Box and see how a JS framework such as Dojo can assist in their development.
Why Dojo?
Choosing Between the Basic Select, ComboBox, and FilteringSelect
Dojo provides widget replacements for most every HTML form element, including
the form itself! The dijit.form.Select
widget replaces the standard Select control.
It doesn't add much to the regular Select other than additional styling capabilities.
Like all the basic Dojo replacement widgets, its main purpose is to make the
look and feel consistent among all form controls.
For a more feature-rich Select,
you may choose between the dijit.form.ComboBox
and dijit.form.FilteringSelect
.
These widgets are very similar in appearance to the basic dijit.form.Select
,
but differ fundamentally in behavior and functionality. ComboBox lets you type
whatever you wish, acting like an auto-complete textbox (see my series
on the auto-complete textbox for more on that). FilteringSelect validates
inputted text to the values in the drop-down. Hence, it more closely resembles
a drop-down augmented with type-to-select functionality, as it restricts you
to entering values that exist in its drop-down.
This feature is an important one because you can't realistically set a child listbox's options based on a nonexistent value. Therefore, it makes much more sense to stick with either the basic Select or FilteringSelect. I'm going to go with the latter so that I can make the user's experience the best it can be!
Representing the Associated Data Lists
Before the advent of object literals and JSON in JavaScript, it was an ongoing challenge to represent the linked data as a JavaScript data type. Developers were forced to resort to multi-dimensional arrays or functions that masked the array creation! Here is the original two-list implementation:
That was simple enough to deal with because all that we needed to do was set the child according to the ordering of the parent list. Things quickly got messy as we added more levels:
I attempted to simplify the array structure by storing each list's items in a separate one-dimentional array. I relied on indentations to distinguish the depth while the code employed empty arrays as delimiters. I thought that it was a good solution, but the number of emails I received from confused readers told me otherwise!