Chained jQuery UI Comboboxes

I started working on a  Chrome extension on my spare time and I was hoping to get a key functionality from  jQuery UI’s combobox, an extension of the autocomplete widget. Much to my dismay, the extension isn’t all that intuitive and the documentation might not be 100% accurate.  I found workarounds for some flaws and others I had to recode. In case you wan’t to spare the long explanation, I’ll leave the download link and the example right here. Sorry for the iframe but I won’t spent time embedding the combox in my current site.

Download: https://gist.github.com/3260658

The long explanation. Let’s see some flaws un the default combobox, and their workaround.

1.- Detecting Combobox Change Event: Selecting an option from the combobox doesn’t trigger the change event. It doesn’t trigger the select event either.  After googling a lot it turns out the event is called “selected”. Kudos to Scott Gonzales, so, in our example, when initializing the combobox control we should bind some acctions to the “selected” event. For example, if you wanted to change another select control value according to the current’s one:

2.- Changing Combobox value programatically: So, now we binded an action to the combo changing, but soon enough we’ll discover that changing that #otherselect value won’t change the corresponding combobox. While changing’s #otherselect’s combobox will indeed change the underlying #otherselect value, changing #otherselect’s value won’t change it’s combobox. This means that using

jQuery('#childselect').val(value):

doesn’t have any effect on the combobox. So the behaviour we binded to the selected event of #myselect isn’t fit to the task. One workaround I found on several discussion boards was to use

jQuery('#childselect').data("combobox").input.val(value);

And I used this one, for a while.

3.- Filling combobox with big datasets. Comboboxes are a special case of autocomplete input, which are neat from UI point of view, but more important, allow the user to interact with big datasets (10.000+ options) which would deem traditional select controls almost unusable (they use them anyway in government websites). So speed is a key issue and if comboboxes take 5 seconds to draw 10.000 options then it’s a major setback.

I was trying to adapt the suggestion from Joe Angus’s “Optimize your Javascript” article -without success- when I came across a discussion thread at StackOverflow named -very conveniently “jQuery UI Autocomplete Combobox Very Slow With Large Select Lists“. So yes, I wasn’t the first person to notice the issue. In that same thread the user gary gave a brilliant answer, a combobox variation which uses queues and avoids innecesary re-rendering of the option list.

This implementation isn’t perfect either. It uses of a button instead of an a element with button behavior, and  and it doesn’t use a span wrapper with ui-combobox classname. This changes the UI theming and the input’s height doesn’t match the button’s.  I took mental note this had to be adressed.

4.- Filtering a child combobox according to a parent selection.  When having two comboboxes in the same page the only workaround I found to narrow down the child-select according to the parent-select was to empty the child-select and fill it again according to certain criteria, which is not optimal when working with several thousand options. Any other path came to a dead end due to the fact that you can’t hide options in select elements, and comboboxes are just divs containing an unordered list, whose ul element maps to the underlying select and each ul’s li element maps to each select’s option with no id or classname whatsoever.

This is where I decided to rewrite the extension, and this is how I did it.

  • The parent select has an id (let’s say #parentselect )
  • Each of the parent select’s options has an id which equals its value attribute. It is a unique code. For example, Alemania will be id=1 and Angola id=2

  • The child select has an id (let’s say #childselect)
  • Each of the child select’s option has an id which equals its value attribute and, just for ease of use, it’s made of its parent category code dash a unique code. It also has a classname which matchest its parent unique code. For example, Alemania’s cities will have class 1 and id’s starting with 1, while Angola’s cities will have class 2 and id’s starting with 2.

  •  My combobox variation for the combobox has slight changes over the aforementioned stackoverflow’s variant, to recover its CSS theming while preserving improved funcionality. It also extends the default funcionality in two ways: First: it gives an explicit ID to the input element of the combobox, which is the concatenation of ‘input_’ plus the id attribute of the underlying select. For example, for #parentselect it would be #input_parentselect. This way you can interact with the text input directly. Second,when mapping and filling the unordered list for the combobox, it will give each li element   an ID matching the option id (with a prefix so it won’t break anything) and a classname matching the parent select category, which will allow for the filtering based of classname. I have no use for the ID attribute, but you might have, so there you go. The above option elements will create the following li elements:

 

  • When initializing the comboboxes, you’ll give both of them a behavior which bonds them toghether. The parent filters the available options in the childs. The child changes the current option in the parent.

 

 

Leave a Reply