Combo Select Boxes In jQuery
Although the standard <select> input for HTML forms supports a “multiple” attribute which allows users to select multiple options by control- or command- clicking, it’s easily one of the most confusing concepts for users to grasp. It’s also fairly clumsy, especially when the list of options is long. It’s difficult for users to see which options they have already selected, and if their previous selections scroll out of site, they get nervous that those choices will be lost when they make additional selections.
A more friendly and intuitive solution is to allow the user to create a new list of selected items by moving them from the original list into the new list. This keeps their (usually much smaller) list of selected items in constant view, and removes those items from the original list, making it shorter and easier to scan for any additional items they might wish to add.
I’ve been using these “combo select boxes” for many years, but a recent project provided me with the opportunity to recreate them with better markup, and using jQuery to control the behavior.
The Markup
I wanted to keep the markup as light and simple as possible, so I stuck with basic form elements. Classes are used as the “hooks” for the javascript so that you can manage multiple lists in a single page.
- There are two <select> inputs, classed “left” and “right” — users will move items from the left (original) list to the right (new) list.
- There are two <input> elements of type “button”, classed “add” and “remove”, to control the movement of items between the lists.
- The buttons are wrapped in a <fieldset> so that they can be positioned as a group via CSS.
- The grouped buttons and the two lists are wrapped in an additional <fieldset>, with an associated <label> element, so that the entire control can be treated as a single element when integrated with the rest of your form.
- The one slightly unusual bit of markup here is the addition of an ID on each <option> element. This helps us keep the lists sorted as items are moved between them (explained below).
<label for="letters">Letters</label>
<fieldset id="letters">
<select id="lettersleft" name="lettersleft" class="left" multiple="multiple">
<option id="opt1" value="1">AAA</option>
<option id="opt2" value="2">BBB</option>
<option id="opt3" value="3">CCC</option>
<option id="opt4" value="4">DDD</option>
<option id="opt5" value="5">EEE</option>
...etc...
<option id="opt26" value="26">ZZZ</option>
</select>
<fieldset>
<input type="button" class="add" value=" > " />
<input type="button" class="remove" value=" < " />
</fieldset>
<select id="lettersright" name="lettersright" class="right" multiple="multiple">
</select>
</fieldset>
Adding Behavior
jQuery’s built-in DOM manipulation methods made short work of the basic functionality. I used .parent() to traverse back up the tree to the master <fieldset>, and .find() to target the left and right lists respectively. Moving <option> elements between the two lists is a snap with .append():
$('input.add').click(function(){
var left = $(this).parent().parent().find('select.left option:selected');
var right = $(this).parent().parent().find('select.right');
right.append(left);
sortBoxes();
});
$('input.remove').click(function(){
var left = $(this).parent().parent().find('select.left');
var right = $(this).parent().parent().find('select.right option:selected');
left.append(right);
sortBoxes();
});
You’ll notice the call to a sortBoxes() function. The usability of this type of control is greatly enhanced if the lists are sorted as each change is made. For that, I used Guillaume Andrieu’s Selso plugin <http://plugins.jquery.com/project/selso>. A cool feature of this plugin is that it can simultaneously sort multiple lists with the given criteria, since it sorts individual elements within their respective parents. So, all I had to do is select all of the <option> elements from the left and right lists, and tell the plugin how I wanted them sorted. I also deselected any selected elements:
function sortBoxes(){
$('select.left, select.right').find('option').selso({
type: 'alpha',
extract: function(o){ return $(o).text(); }
});
// clear all highlighted items
$('select.left, select.right').find('option:selected').removeAttr('selected');
}
And that’s it! As usual with jQuery, not a lot of custom code required. I considered wrapping this up into a plugin, but I think I’ll wait until I’ve used it in a few more places to see what options would be the most useful. You can try out a demo here: <http://devblog.jasonhuck.com/assets/comboselect/>.






There is a nice jQuery plug-in that does all those things -
http://www.texotela.co.uk/code/jquery/select/
@Yuri:
Yep, I’ve seen that. It seems like a nice, general purpose plugin for working with select inputs. However, it might be nice to have something more specific for creating the combo-select type of control as well, i.e., you start with a normal, single multi-select input in your markup, and transform it into a combo-select via a plugin like so:
$(‘myselect’).comboselect();
That’s probably what I’ll do with this at some point…
Nice! This example is so much more usable than the fragile control-click of a multiple select element. A bit more work, of course, but the payoff is user confidence and a clearer UI.
Nice job, looking forward to the plugin! Perhaps this would make a nice feature: optional doubleclick to transfer the value.
Nice script !! i like the order of options doesn’t lost..
if u can help, i need to change the order of options in the same select box, but i didn’t has sucess to do this with jquery!
help =P
I finally got around to wrapping this up into a plugin:
http://plugins.jquery.com/project/comboselect
You can try out a demo here:
http://devblog.jasonhuck.com/assets/comboselect_plugin/
You can set the labels for the add/remove buttons, choose whether to sort either column, and, by request, you can double-click to transfer items between lists.
Enjoy!
[...] a followup to my previous post on creating comboselect boxes in jQuery, I have automated the process of transforming a normal multiselect input element into a comboselect [...]
Hi,
Great article, found it useful. I have one question: why do you do
var left = $(this).parent().parent().find(‘select.left option:selected’);
instead of
var left = $(‘select.left option:selected’);
?
Cheers
@Dave,
That’s to keep options from one set of boxes from ending up in another, if there are multiple sets on the same page.
- Jason
Hi There,
Nice work on combo select, it surprised me that this hasn’t been implemented before.
anyhow, i’ve come accross an issue with ie6 where selected items are not transferred to the right combo box on initiation.
I’m trying to fix it, and will post back if i succeed
I think you need to add the attribute selected=”selected” to the selectbox that contains the selected values. Otherwise there will be nothing posted with the form.
Regards
Looks good.
Is it possible to offer a “Remove all” button as well as “Add” and “Remove” buttons?
Col
[...] Wheel 2.0: Jason Huck’s Devblog » Combo Select Boxes In jQuery (tags: ComboBox jquery) [...]
[...] Wheel 2.0: Jason Huck’s Devblog » Combo Select Boxes In jQuery (tags: ComboBox jquery) [...]
Hi Jason,
I modified the code comboselect plugin to work with the Select Box Manipulation jQuery plugin, instead of Celso plugin. You want to get my changes?
Regards,
Sergio.
very elegant solution, that helped me out lots, thanks
Doesn’t work in IE 7