This is the successor and port of my original jQuery MultiSelect Plugin to a jQuery UI widget. While both will actively be maintained, I highly recommend you use this version over the plugin version. It has a more robust feature set, is faster, and is much more flexible. MultiSelect turns an ordinary HTML select control into an elegant drop down list of checkboxes with themeroller support.
This version inherits all the benefits from the jQuery UI widget factory that are not available in the plugin version. The most requested feature was the ability to call methods on instances after initialization (e.g., statefullness), and now there are 10 to choose from! Also present are eight events you can bind to, which in the previous version, had fewer and limited support. Finally, there is support for effects. Just include the jQuery UI effects dependency and specify the name of the opening or closing effect to use (and speed, if you wish!)
- Current version: 1.3 (07/08/2010 – changelog)
- View demos
- Download source or minified, and the CSS file.
- Follow this project on GitHub
- Run unit tests
Demo
See what you’re missing out on? Many more demos are available here.
The code behind this demo:
$("#multiselect-demo").multiselect({ show:"blind", hide:"blind", selectedText:"# of # selected" });
Usage
Using this widget is simple. First, include the following files:
- jQuery 1.4.2
- jQuery UI 1.8 widget factory and effects (if you’d like to use them)
- A jQuery UI theme
- This widget: jquery.multiselect.js
- The CSS file: jquery.multiselect.css
Next construct a standard multiple select box. If you want this widget to degrade gracefully when JavaScript is turned off, ensure the control has the multiple attribute:
<select id="example" name="example" multiple="multiple"> <option value="1">Option 1</option> <option value="2">Option 2</option> <option value="3">Option 3</option> <option value="4">Option 4</option> <option value="5">Option 5</option> </select>
Finally, initialize the widget on the select box once the document is ready:
$(document).ready(function(){ $("#example").multiselect(); });
See the demos for advanced usages and for more documentation!
Options
To further customize multiselect, pass in a object with one or more of the options below.
// example: $("select").multiselect({ header: "Choose an Option!" });
| Option | Description | Default |
|---|---|---|
| header | Either a boolean value denoting whether or not to display the header, or a string value. If you pass a string, the default “check all”, “uncheck all”, and “close” links will be replaced with the specified text. | true |
| height | Height of the checkbox container (scroll area) in pixels. If set to “auto”, the height will calculate based on the number of checkboxes in the menu. | 175 |
| minWidth | Minimum width of the entire widget in pixels. Setting to “auto” will disable. | 225 |
| checkAllText | The text of the “check all” link. | Check all |
| uncheckAllText | The text of the “uncheck all” link. | Uncheck All |
| noneSelectedText | The default text the select box when no options have been selected. | Select options |
| selectedText |
The text to display in the select box when options are selected (if selectedList is false). A pound sign (#) will automatically replaced by the number of checkboxes selected. If two pound signs are present in this parameter, the second will be replaced by the total number of checkboxes available. Example: "# of # checked".
This parameter also accepts an anonymous function with three arguments: the number of checkboxes checked, the total number of checkboxes, and an array of the checked checkbox DOM elements. See examples for usage. |
# selected |
| selectedList | A numeric (or boolean to disable) value denoting whether or not to display the checked opens in a list, and how many. A number greater than 0 denotes the maximum number of list items to display before switching over to the selectedText parameter. A value of 0 or false is disabled. | false |
| show | The name of the effect to use when the menu opens. To control the speed as well, pass in an array: ['slide', 500] |
empty string |
| hide | The name of the effect to use when the menu closes. To control the speed as well, pass in an array: ['explode', 500] |
empty string |
| autoOpen | A boolean value denoting whether or not to automatically open the menu when the widget is initialized. | false |
| multiple | If set to false, the widget will use radio buttons instead of checkboxes, forcing users to select only one option. | true |
Events
Hook into any of the events below by either binding to the event name, or passing in the name of the event during initialization:
// bind to event $("#multiselect").bind("multiselectopen", function(event, ui){ // event handler here }); // or pass in the handler during initialization $("#multiselect").multiselect({ open: function(event, ui){ // event handler here } });
| Event | Description |
|---|---|
| beforeopen | Fires right before the menu opens. Prevent the menu from opening by returning false in the handler. |
| open | Fires after the widget opens. |
| beforeclose | Fires right before the menu closes. Prevent the menu from closing by returning false in the handler. |
| close | Fires after the widget closes. |
| checkAll | Fires when all the options are checked by either clicking the “check all” link in the header, or when the “checkall” method is programatically called (see next section). |
| uncheckAll | Fires when all the options are all unchecked by either clicking the “uncheck all” link in the header, or when the “uncheckall” method is programatically called (see next section). |
| optgroupToggle | Fires when an optgroup label is clicked on. This event receives the original event object as the first argument, and a hash of values as the second argument:
$("#multiselect").bind("multiselectoptgrouptoggle", function(event, ui){ /* event: the original event object, most likely "click" ui.inputs: an array of the checkboxes (DOM elements) inside the optgroup ui.label: the text of the optgroup ui.checked: whether or not the checkboxes were checked or unchecked in the toggle (boolean) */ }); |
| click | Fires when a checkbox is checked or unchecked.
$("#multiselect").bind("multiselectclick", function(event, ui){ /* event: the original event object ui.value: value of the checkbox ui.text: text of the checkbox ui.checked: whether or not the input was checked or unchecked (boolean) */ }); |
Methods
After an instance has been initialized, interact with it by calling any of these methods:
// example: $("#multiselect").multiselect("method_name");
| Method | Description |
|---|---|
| open | Opens the menu. |
| close | Closes the menu. |
| update | Updates the current selectedText/selectedList value. Useful if you manually check/uncheck a box and need the widget’s text to reflect the changes. |
| disable | Disable the entire widget. |
| enable | Enable the entire widget. |
| checkAll | Check all checkboxes. |
| uncheckAll | Uncheck all checkboxes. |
| isOpen | Returns a boolean denoting if the widget is currently open or not. |
| getChecked | Returns an array of all the checked checkboxes. |
| widget | Returns the menu container (all checkboxes inside). |
| setOption | Set or change one of the options after the widget has been initialized. The new option setting will take affect immediately. |
| destroy | Destroy the widget, and revert back to the original select box. |
Filter Plugin
A filtering widget is available which, once initialized on a multiselect instance, will insert a text box inside the widget header. Typing in the input will filter rows and return matches in real time. To view a demo, download, or read the documentation, head to the demo page.
How do I…?
These questions came out of the comments which others will probably find useful:
Set default options for all multiselect instances?
The options object is located in $.ech.multiselect.prototype.options. To configure options that all new instances will inherit, it’s easier to set them in this object instead of on an instance-by-instance basis.
$.ech.multiselect.prototype.options.selectedText = "# of # selected";
Retrieve an array of all selected values?
Call the getChecked method and map a new array:
var array_of_checked_values = $("select").multiselect("getChecked").map(function(){ return this.value; });
Retrieve values on the server?
Depends on your server-side language. In PHP et. al., you may need to name your select with square brackets on the end so the values can be captured as an array. I will probably wind up implementing this as an option at some point so it’ll degrade a bit better.
Prevent the selectedList option from increasing the button’s height?
Open up the CSS file and edit the .ui-multiselect declaration.
.ui-multiselect { height:25px; overflow-x:hidden; padding:2px 0 2px 4px; text-align:left }
The height you’ll need to set depends on the font size and padding you use, so it may need adjusting.
If you find any issues, please report them using the GitHub issue tracker. Thanks!
Related posts:
- jQuery MultiSelect Plugin w/ ThemeRoller Support
- A jQuery UI Growl/Ubuntu-like Notification Widget
- Tips for Developing jQuery UI 1.8 Widgets
Tags: jQuery, jquery ui, multiselect









Definitely looking good, but keyboard support should be the next priority. In our research, we've found that a large number of application users still prefer to use the keyboard for input. Being able to arrow through and use the space bar to select/unselect options would go a long way to improving the UI.
Clicking the down arrow in Chrome opens & immediately closes the dropdown menu. Minor bug, but otherwise it looks good
What version are you testing in? I'm unable to reproduce this in 6.0.453.1 dev (linux) or 5.0.375.99 (windows)
5.0.375.86 on Windows 7. The behavior looks as though the down arrow icon and the textbox are both calling toggle, for the drop down menu, at the same time.
I see it now – thanks. Fixed: http://github.com/ehynds/jquery-ui-multiselect-...
Will be releasing 1.3 soon with this included.
Wow, great improvement! This new version couldn't come in better time. The destroy method really make it easier now for me to dynamically make copies of the multiselect. The getChecked too will be handy.
Thanks again.
(It's Refactoring time!)
I wrote a filtering plugin for this widget tonight, available for testing here:
http://www.erichynds.com/examples/jquery-ui-mul...
It's definitely still in alpha as I've barely tested it and I'm sure there are a lot of logistics to pan out. Feedback is encouraged!
I havee 3 select boxes in a vertical alingment
1) with all having autoOpen=true. Only last selectbox opens on load, the first and second are closed.
2) I like to have them all open and arrange the vertical position automatically accordning to the height of opening dropdown menu. Now the header is fixed and when one dropdown menu opens, it covers the one below.
hey folks. is it possible to get the selected names instead of “1 of 30 selected”?
http://dropdown-check-list.googlecode.com/svn/t...
as seen here.. would love to use this widget, cause its faster.. but need the selected names
Take a look at the “selectedList” option, or the demo showing you how to pass a function to selectedText.
Hey,
in the methods table of the documentation above you wrote “checkall” and “uncheckall” instead of “checkAll” and “uncheckAll”. It seems these methods only work if written camelCase.
yeah. got it. thx a lot.
any plans on integrating this into the UI? would be cool? maybe the author wanna talk to the ui team
Good catch – fixed. Thanks
The first initialisation works, the selected items in the html select are getting selected in the multiselect.
After a refresh I still have my multiselect, but none of the items are selected.
$.fn.multiSelect.defaults.XXXXXXXXXXXXX
doesn't work on that version from previous implementation.
Great widget but I need help. It seems that if i use this in a form the select field never makes it into the POST of the http request. Am I missing something?
how do you access the getChecked array?
Again nice job! I have two things for you.
Does this version support Overriding Options?
Also here's a bug I've encountered. In IE6 & IE7 when I have more than 107 items selected the multiselect fails to submit the form without any type of error message indications. FF3 and IE8 work.
it's now $.ech.multiselect.prototype.options;
what's your server-side language? you may need to add brackets to the end of your select name.. I will probably add an option for this in a future release.
var array_of_selected_boxes = $(“select”).multiselect(“getChecked”);
What do you mean by overriding options? You can set them once globally under the $.ech.multiselect.prototype.options namespace, individually by passing an object when you init the multiselect, or use the setOption method.
I'll check into that bug; thanks for the report.
By overriding options I meant the default options.
Where the plugin was: $.fn.multiSelect.defaults.minWidth = 500;
The widget is now : $.ech.multiselect.prototype.options.minWidth = 500;
You might want to document that change under the Options section.
Also I dont see the setOption method listed above in the Methods list.
Thanks!
Another question on Options.
Has the “position” option been removed from the widget? I found it useful for a long multiselect list that is at the bottom of a page. I set it to “middle” or “top” depending on the list size so the user didnt have to scroll down the page any more than necessary. (Note: I also customized the widget to display the title of the multiselect in the header so the user knows what control they are modifying. This was especially useful when the position was set to “middle”.)
Thanks!
Hi, I've been contemplating to use your very neat multiselect plugin. However, I've been having some problems. Today I tried the Single Select in IE8 and I can select multipe radio buttons (which is being reflected in the selectedText as well).
I've also had some bad luck with using it in my existing app, my other jQuery script stopped working. Do you think I'm just having a bad day / bad luck or should is your srcipt a bit too early in the release cycle to be used in production? Will it work in IE7?
Sorry for being a bit vague about my experience, but I'm not at work and I think my kid is going to wake up soon
I do believe your plugin looks great and I hope to use it for both multi select and single select, because I want to keep my plugins to a minimum (alternative would be to include Filament Groups single select, but if I can avoid it I think it would be better for maintenance).
Right now I'm using asmSelect and Stylish Select, but been having problems with newer versions of jQuery and jQuery UI. And since we're already using UI I hope this to be a more unified solution. It is a jQuery djungle out there
Any advice is appreciated.
Thanks,
Claes
yes – I am attempting to move that logic to the jQuery UI position utility, which will allow the menu to automatically flip if it's near the end of the page. I'm finding it to be quite buggy, however.
Claes, there shouldn't be any conflicts unless one of your other plugins is also named multiselect. Also make sure you're using jQuery 1.4.2 and jQuery UI 1.8. I will look into that single select bug.. what have you named your select? Can you inspect the radio buttons with firebug and see if their names are different?
Hi again, thanks for the clue. I was using jQuery 1.4.1 due to some other circumstances in my project. Now I'm using 1.4.2 and it works like a charm. I'll get back to you about the IE8 problem. I'll see if I can reproduce it at my Windows computer here at home. The problem occured at your demo page.
I think the question is how do you get an array of ids of the checked elements?
Keep up the great work!
Hi, thanks for your fine plugin.
I want (or should;-) change the style of the UI-Element to another color – IF there are options selected. Background: it should be used in a big search-form with 8 or more Multi-Selects.
I explored the “close”-event – but how can I access the Multi-Select-Widget from within that callbackfunction? Is there a generic way? Or should I reference it with another
jQuery('#id_of_element')
call? Once I have the a reference, I want to call its getChecked-Method and add/remove a specific class for highlighting.
this will give you an array of checked values. customize to return whatever value you want:
var array_of_checked_values = $(“select”).multiselect(“getChecked”).map(function(){
return this.value;
});
“this” in the callback is a reference to the select box. so in your case, $(this).multiselect(“getChecked”)
The problem with IE8 and Single Select appears at my Windows box at home as well. If you have IE8 available, try it with your demo page and you'll probably see the same.
I failed to inspect it any further with Firebug though. Had to use Firebug Lite in IE and there seems to be a bug in Firebug Lite when inspecting your demo page – it failed with something like Access Denied.
Thank you. I must confess, with al little guessing/thinking I should have found the solution by myself…
But another challenge: any clue how it is possible to change the height of the “dropdown” dynamically, in dependence of the item count (like a “real” dropdown)
I see it. the problem was with the demo,l there wasn't a name set on the select box. all fixed now.
While showing my site to a friend, he noted that it would be nice if the option exists to show the dropdown in multiple columns. I've got one with 150 entries in it, would be just plain awesome if I could say, “put those in 3 columns” so that a lot less scrolling would take place.
But I know that's probably not an easy thing to do.
Great job. I'm a having a problem when I use both “optgroup” in the select and the filtering plugin.
In this case, the filter is not working, do you have the same problem?
another good catch.. i just updated the plugin: http://github.com/ehynds/jquery-ui-multiselect-...
you'll have to pull the latest version of the widget & the filtering plugin. there are still some styling issues to address, like hiding the optgroup label if none of it's children match, but the logic should be pretty solid.
Hey,
Can i use image + text in the options ?
I can't find a way to do ti …
Thanks
The selected text wraps now when it gets to the end, any way to get that to go back to the way it has worked before, scrolling out of view? Or just chop it off? I can't have my buttons growing on me, but I'd hate to not use selectedText just because a few very large options warp the button.
Add these CSS properties to .ui-multiselect:
.ui-multiselect { height: 25px; overflow-x: scroll; }
I don't want to set this by default because I don't want to impose a fixed height. Play around with these properties though to fit your needs.
Out of the box, no… but once the widget is initialized, you can certainly add whatever you'd like to each list item.
any clue how it is possible to change the height of the “dropdown” dynamically, in dependence of the item count (like a “real” dropdown)
Set the height option to “auto”
Great plugin. I found it useful to add a method as follows:
getAll: function(){
return this.menu.find(“input”);
},
to get an array of all the checkboxes in the list (in my case, I wanted to automatically check/uncheck other boxes with identical text within other optgroups).
Eric, how close the menu with the options in Single Select after choosing the option I chose?
It would be very interesting to put an option to choose whether we wish to close the menu by choosing the option.
My code is as follows:
$(“#cursos”).multiSelect({
minWidth: 400,
multiple: false,
showHeader: false,
selectedText: function(numChecked, numTotal, checkedItem) {
vCodCurso = $(checkedItem).val();
alert('closing…');
$(“#cursos”).multiselect(“close”);
alert('closed?');
return $(checkedItem).attr(“title”);
}
});
uncheckAll (not sure about checkAll) doesn't seem to work when the filter is present. Pre-widget my jQuery was finding the “none” link and clicking it. Any multiselect with a filter wasn't “none”-ing. Switched to using the uncheckAll method. Same problem.
The only way either method (finding the link and clicking or using the method) works is if the multiselect “dropdown” is visible. When it isn't, no worky.
Thanks. fixed: http://github.com/ehynds/jquery-ui-multiselect-...
I'll figure out a solution for you… the problem is that I have to detach the option tags from the DOM when the widget is initialized, otherwise the original select and the new multiselect would be sent during form submission. The other option I have is to keep the select in tact and just disable it, but then I run into problems with destroy() and trying to figure out which options should be re-enabled and which ones were originally set to disabled.
Destroy/reinitialize definitely shouldn't be appending new options, so I'll check into that first.
Just wanted to say that I'me seeing the same behavior regarding new options being appended to the old options doing a destroy/initialize.
Awesome awesome plugin! Any chance of having a “template” for the selected options so we could feed things like images and other styles into the items?
How can I dynamically add <options> to the widget?
(nice work btw ^^)
Thanks for the great plugin, i have little problem.
how can set the default checked value on when using multiselect:false.
I used this, but didn't work :
$(“[name=driver_code]“).each(function(){
if($(this).val() == data.driver_code) {
$(this).attr('checked', true).trigger('change');
}
}) ;
Yes, the radio get checked, but the header is not.
I have try the filter with single select (multiple:false), and the result is not accurate sometimes right sometimes wrong, but there is no problem on multiple:true.
how stable is this filter ?
Thanks!
Just a little concern related to widths. My multiselect is inside a dialog that is initially closed. So, when I call the plugin on my select element it is by that time hidden and thus has 0 width. I obersved that you set the width of the menu based on the width of the button which will also have no dimensions. As a consequence, the menu is rendered without a width css property and that caused me some layout problems on my form.
I solved it for my particular case but don't know what would be the generic solution. Just mentioning it so that in future releases you'll have that issue in mind.
Hi, great widget!
I found an issue though:
if I load jquery.validate.js in the same file as the multiselect, the selection of options doesn't update the text in the control. (as '1 item selected', 'x items selected', etc).
I thinks found the problem,
i'm not using multiple=multiple attribute, and i'm add the extra <option> with 0 value …
After using multiple attribute and remove the exprta <option> the filter works great ….
Found the solution ..
The solution is, using .trigger('click'), but there is one more problem ..
How can i pass extra data to this trigger and capture it on multiselectclick event ?
.trigger('click',['edit'])
….
.bind('multiselectclick', function(event, ui) …
.., on ordinary click event we can get the data via second argument of click call back..
.bind('click', function(event, extra_param))…
What about multiselectclick event ?
I hope the question is clear anough …
Thanks!
This is amazing job Eric! I've being looking for auto suggest / complete scripts, and while there is all kinds of options out there and this is not in the same field at all, it is an alternative way of doing it, actually better for this specific need, and I can't believe this is open source, so easy to use, and works so good!
Anyway, since you encourage feedback in here, I think I got a bug on the filtering. Try using more than 1 word per <option>. This is what triggered me (sorry for the portuguese):
<select multiple=”multiple” name=”usuarios” id=”usuarios” style=”width:400px;”>
<option value=”0″>teste</option>
<optgroup label=”teste estatico”>
<option>fulano da silva</option>
<option>beltrano da silva</option>
<option>ciclano oliveira</option>
</optgroup>
</select>
if you search for “s” or almost any letter, it won't show the last 2 options. I will look in the code later on, since it's so small, and try to figure it out myself… But I just wanted to say it in here, in case you find this easy to fix.
Thanks again for such a fantastic piece of work!
Just an update, I'm positive the problem is actually with OPTGROUPS, but can't pinpoint where in the code – a lot to learn on jquery before I can easily handle this.
Here is a “little” feature request list, in order of complexity (I suppose):
- option to set the layout as a regular select multiple rather than combo dropbox (just like the <select multiple> would behave not for this widget)
- auto complete / suggest search style, besides the filter
- keyboard support
There is a problem with other submit buttons e.g. into cart. They won`t function with loading multiselect.js
Eric, excellent widget.
Is there any way to customise the options to be wider than the widget width itself? I am trying to avoid the option text wrapping, but need to keep the widget itself narrower. In the Safari web inspector I can simulate the required effect by explicitly changing the width of the ui-multiselect-menu element (which has an inline width). But I can't see where I can set this in css or in the javascript.
Appreciate any suggestions.
Thanks.
How could I change the state of one of the checkboxes to checked/unchecked?
Error on page in the example:
// bind to event
$(“#multiselect”).bind(“multiselectopen”, function(event, ui){
// event handler here
});
It should be:
// bind to event
$(“#multiselect”).multiselect('widget').bind(“multiselectopen”, function(event, ui){
// event handler here
});
I believe that $(“#multiselect”)[0] is the plain <select> in a HTML, right? No option, right!
How about 'textChanged' event?
It's so lazy to write this:
$('#MySelect').multiselect('widget').bind('click checkAll uncheckAll',function(event, ui){ …
Regards.
Bug!
The “close” event may be attached only in the initialization.
No one “someTing.bind('close',function(ev,ui){…” do not work.
Hello,
I am trying to do a form POST but the values from the selects are not passed?
Good job. I obviously have many of the feature requests that others have, but what about classes? It seems like any hope of doing different styles for different opt groups is out of the question. I understand that you're using themeroller, but why not put the option there for multiselect to optionally get the classes from the original elements? It severely limits what I can do.
I keep getting:
'this.button.contents().1' is null or not an object
on this line in the jquery.multiselect.min.js (v1.3):
return this.button.contents()[1].nodeValue=c
Any ideas?
It's a bug…specifying
noneSelectedText: “”
causes an error
The demo syntax is correct – you interact with the widget by referencing the original select box.
something like: $(“select”).multiselect(“widget”).find(“input:checkbox”).trigger(“click”);
you would of course have to add some kind of filter to grab the checkbox you want.
See this demo: http://www.erichynds.com/examples/jquery-ui-mul...
I'm trying to keep the API and code base to a minimum, but allow hooks to cover all these special cases.
set the selected=”selected” attribute on the option tag you want checked by default. when you transform the select into a multiselect, it will be checked automatically.
You need to bind multiselectclose – not close – and make sure you're selecting the original select element you initialized the plugin on.
What server side language? You may need to name your select box with brackets at the end – like “countries[]” – in order for your backend to pick it up.
Is there already a solution for this issue? Adding the validate.js also stops most of the other functions of the multiselect.
I to need to do this but am new to javascript and your control. Could you expand your answer as it's not too clear what you mean by filter.
When I try the above code, the script fails. I've uploaded 1.3. Any ideas?
To clarify, when I use the example “var array_of_checked_values = $(“select”).multiselect(“getChecked”).map(function(){
return this.value;
});”
and output to an alert box to see the values I get [object object].
this is normal behavior; you cannot alert a complex data type. use firebug and console.log() the variable.
Hi,
I will put your control in a bottom bar, but, I don’t find how to open it up
Any idea on it ?
Great job!
How do I add and remove options?
I realized my mistake yesterday and was able to get everything working. The only issue I have now is with the previous version when open the menu did not affect the other elements in the form. It overlaid them. This version pushes all other items down the page. Is there a setting to overlay?
Great plug in by the way.
Very nice widget
does almost everything I need for what I’m working on.
I do have a question though and that is how (if possible) can I extract the index of a selected value, especially for lists where multiple: false.
Thanks