Ben Sgro, one of the newest editions to the cadre of arc90 developer extraordinaires, has created a new version of our MultiSelect tool, this time written in jQuery. It has been added to the Arc90 Tools section at the Arc90 Lab.
jQuery MultiSelect, much like its predecessor, is an easy way to turn an HTML select into a stylish drop down that supports multiple selections in a compact view.
If you are not familiar with jQuery, their homepage slogan is “The Write Less, Do More, Javascript Library”. The following source code comparision reinforces that claim.
| Javascript MultiSelect | jQuery MultiSelect | |
| Lines of code* | 422 | 225 |
Not only does the new version have a significantly smaller source code footprint, it is also easier to follow than the original. This is partially due to the powers of jQuery, allowing complex DOM manipulation and method chaining to accomplish tasks with less code while still maintaining readablity.
* Our lines of code comparision was done by removing all comments that occupied one or more lines. Whitespace does count in the total.
Joel Nagy said:
I applaud Ben on redeveloping my original MultiSelect tool to work with jQuery. It’s definitely one of the best JavaScript libraries available. I was actually thinking of porting it myself the other day, so I’m glad that it is getting new life.
I do however think that a comparison on the number of lines is inadequate in the measure of footprint. You should actually measure the bytes of the file, and you do have to take into account that the jQuery version also requires the jQuery library (which if you are already using it, is not a big deal, but does add a considerable amount of bytes to the overall footprint) and the original version is completely self contained and can be added to any site no matter what JavaScript code may already exist.
Chris LoSacco said:
Joel -
You’re absolutely right. The lines of code comparison doesn’t take into account all of the factors that go into comparing a port from one codebase to another. There are many things to consider when writing a plugin to a framework (lack of standalone operation and size being the biggest I think, as you point out), and since we don’t really bring them up in the post, you’re definitely justified in your comments. :)
The multiselect idea is a really great one, and the initial implementation really got us a long way. It’s used in multiple products at Arc.
We also have a couple of plugin ideas that I’m sure will be cool for you to see, so keep your eye on the labs and such!
Chris Dary said:
Hey guys,
Curiosity got the best of me, and I did a little research:
jQuery 1.2 + jQuery MultiSelect (packed) = 32K
Joel Nagy’s Original MultiSelect (packed) = 11K
Joel Wins!
Ben Sgro said:
> Joel wins!
Indeed. Well, it was fun to use jQuery to do this, it made working with javascript enjoyable.
Thanks for the feedback!
Ignatius said:
I like this plugin but it could be better if you add an option to clean the selected values on form reset.
And select options by code could be useful too for those ajax forms.
Randy said:
It appears there’s a bug with this plugin? I was suprised to see that the plugin submits parameters with a different name than the multi-select it intends to unobtrusively replace. Check line 320: it creates checkboxes with:
name=”multiSelect-options-’ + id + ‘[]”
when it should simply use:
name=”‘ + name + ‘”
(which was perhaps the original intention since there is an unused ‘name’ local variable in scope).
Otherwise, very cool. Surprising though that this bug hasn’t been noticed? Or perhaps am I missing something?
Jukka-Pekka Keisala said:
I also notice an issue with IE6.
If I put whatever under the dropdown we see the classic IE bug where stays on the top of the the layer. This bug is also in Joel Nagy’s code.
Eva said:
I’m trying to use the bgIframe plugin to solve the bug pointed by Jukka-Pekka Keisala, but I can’t.
Anyone knows how to solve this?
anthony ryan delorie said:
Thanks for sharing this code. What you guys did is wonderful. A few observations…
1) hovering over the dropdown (displaying the title) no longer shows the selections of the dropdown like it does in Joel Nagy’s code
2) Also the Select All shows the number of actual selections plus one (counting the select all selected) unlike Joel Nagy’s code where it correctly shows the number. One could make a case for displaying “All selected” on the dropdown if all selected instead of an arbitrary number especially for a big lists.
Again great script, this really is a great UI upgrade over what people had been using multiselect listboxes for.
Ben Sgro aka sk aka mr-sk said:
@Randy – Thanks for the feedback. We’ll have to update the code.
@Jukka-Pekka Keisala – Thank you also for your feedback. If you have a patch for this bug, please email it to me. You will be provided the proper credit!
@ Anthony Ryan Deloir – Thank you for pointing this out. If you happen to you have a patch, please email it to me. Otherwise we’ll try and do the updates to the code soon.
Thank you all!
Jose said:
@Anthony Ryan Deloir, @Ben – Just change the following in the updateSelectTitle function (line 442):
var selectCount = $(‘:checkbox:checked’, selectList).length+1 – (this.checked ? 1 : 1);
To this:
var selectCount = $(‘li:not(.selectall) :checkbox:checked’, selectList).length+1 – (this.checked ? 1 : 1);
Including the “li:not(.selectall) ” solves the problem.
Bye!
Ben Sgro aka sk aka mr-sk said:
@ Jose – Thanks! I’ll update the source.
BONANNI Aur said:
I’ve found a bug on arc90_mutliselect90.js
When click on “Select All” it counts the “select all” element.
Then you have to replace the line 450 : “var selectCount = $(‘li:not(.selectall) :checkbox:checked’, selectList).length+1 – (this.checked ? 1 : 1);”
by : “var selectCount = $(‘li:not(.a9selectall) :checkbox:checked’, selectList).length+1 – (this.checked ? 1 : 1);”
Steven said:
Cool Plugin. Is there a method or an easy jquery way to select options after the multiselect is instantiated and they are no longer option tags?
Thanks! Steven
Chris said:
I would just figure out what ID’s the function is naming the new checkboxes in the dropdown and call $(‘#theMultiSelectId’).click();
DarkNeo said:
Hi and before all thanks for this js code. Its appears that if we selected the text (not the checkbox), the parameter wich is transmit is the text between TEXT and not the value.
If we select the checkbox, the script works well.
Have you upgrade the script since Randy tell you the bug or not ? Please, send me a mail if you did.
Thanks !
DarkNeo said:
i’m sorry but in my previous message there’s an error (i put html code and it don’t displays) “[..]wich is transmit is the text between <option value=”..”>TEXT<option/> and not the value.[..]“
DarkNeo said:
Sorry, I didn’t see the latest version.
Colin Gibson said:
I’ve just tried adding optgroup tags to my multiselect demo/example in the hope that it would have worked but it doesn’t seem to.
Does anyone have any idea if this might be possible or not if so, how?
Peter said:
How to get the selected values from the multil select?
Could give an example?
Thanks.
Cynthia said:
Hi,
I have the following options box and I could not get the selected values from the option box.
I tried few different ways to get the selected values from the options and all them did not work for me.
Could you please help me (give an example) on how to get the selected values from the multi select dropdown?
Thanks in advance,
Cynthia.
Any
Normal
All
Only
$(function() {
$(‘#MyOptions’).multiSelect();
});
function Getvalues() {
var selected = $(“#SpeedSatelliteTournOptions option:selected”);
alert(’selected.val ‘ + selected.val()); // returns null
alert(’selected.text ‘ + selected.text()); // returns empty string
var optionsObj = $(‘#SpeedSatelliteTournOptions’); //document.getElementById(‘SpeedSatelliteTournOptions’);
alert(‘optionsObj.length ‘ + optionsObj.length); // return zero
alert(‘optionsObj.selected_text ‘ + optionsObj.selected_text); // undefined
}
Cynthia said:
I made a mistake in my last posting (option id was wrong).
Please help (give me an example) on how to get the selected values from the multi select dropdown?
Thanks,
Cytnhia
html code in the commeted section below
$(function() {
$(‘#MyOptions’).multiSelect();
});
function Getvalues() {
var selected = $(“#MyOptions option:selected”);
alert(’selected.val ‘ + selected.val()); // returns null
alert(’selected.text ‘ + selected.text()); // returns empty string
var optionsObj = $(‘#MyOptions’); //document.getElementById(‘MyOptions’);
alert(‘optionsObj.length ‘ + optionsObj.length); // return zero
alert(‘optionsObj.selected_text ‘ + optionsObj.selected_text); // undefined
}
Haw-Bin Chai said:
This plugin looks pretty slick. However, I’ve been trying to work with it over the past few hours, and it really hasn’t been easy. First of all, the documentation doesn’t show you the best way to get values from the list. It omits details on how you can prepopulate the list with values.
It also appears that, as coded, you will not be able to include multiple multi-selects on the same page.
I think another abstraction needs to be pared with this element to allow for more consistent usage – i.e. some kind of API for working with the list. Also, I’d want to be able to set callbacks that are called *after* an element has been selected/deselected – not at the same time.
Haw-Bin Chai said:
Alright, I put my money where my mouth is and wrote an implementation of multi-select from scratch, using jQuery, with similar behavior to the arc90 one. It’s currently cobbled together with some test HTML, but seems to be working quite nicely.
http://stressfreetesting.com/misc/MyMultiSelect.tar.gz
The nice thing is that you get this object with a clean API for both accessing and modifying the multi-list. You can also specify where to anchor the new element when you create the object. Finally, there’s a mechanism for letting you know which entries were modified in the list, given a set of default values.
Works for FF3, IE7, and chrome (haven’t tested others yet). Give ‘er a whirl and let me know if I should package this up more formally.
Chris Dary said:
Haw-Bin Chai,
This is great – I see a few drawbacks immediately (on blur doesn’t hide the select box, you might want to try it with other inputs nearby to test overlay issues), but it looks great overall in terms of developer usability.
If you end up putting it somewhere, let us know and we’ll link to it!
Leanan said:
I’ve noticed a minor bug, not sure when it got introduced:
The following line has the wrong class for the li:not:
var selectCount = $(‘li:not(.selectall) :checkbox:checked’, selectList).length+1 – (this.checked ? 1 : 1);
This is line 449 I believe.
It should be $(‘li:not(.a9selectall). Otherwise it reports as having one more item selected than is actually selected when the selectAll option is selected.
Haw-Bin Chai said:
@Chris:
Thanks for the feedback – I’ll work on making a release-able version. I’m wondering about a couple of things: 1) what is the expected behavior with blur()? I haven’t dealt much with this event. 2) I tried to produce overlay issues with IE6. It has issues with the elements. It seems that the arc90 version does as well – correct?
Haw-Bin Chai said:
I packaged it up. I haven’t yet dealt with blur() and focus(), they seem pretty difficult to get right (see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html). I hope to do so in the future. Download link:
http://stressfreetesting.com/misc/my-multiselect-0.1.tar.gz
Demo:
http://stressfreetesting.com/misc/my-multiselect/my-multiselect-demo.html
Enjoy!
karl said:
I know this isn’t very elegant, but I got tab support working. I added the follownig:
$a = $(‘‘);
$a.focus(function(){selectTitle.click();});
jQuery(this).before($a);
above line 389, so it now looks like:
$a = $(‘‘);
$a.focus(function(){selectTitle.click();});
jQuery(this).before($a);
jQuery(this).before(selectDiv);
jQuery(this).before(selectContent);
karl said:
arg, the HTML got stripped, the first line should be:
$a = $(‘[a href=$#$][/a]‘)
where [, ] and $ are placeholders for less than, greater than and double quote respectively.
karl said:
I was getting endless recursive calls using jQuery 1.3.1, the simplest fix is to find the function name “multiSelect_closeWindow” (line 174) and switch the two lines, so that it goes from looking like:
function multiSelect_closeWindow( )
{
selectTitle.click( );
$(‘body’).unbind(“click”, multiSelect_closeWindow);
}
to looking like:
function multiSelect_closeWindow( )
{
$(‘body’).unbind(“click”, multiSelect_closeWindow);
selectTitle.click( );
}
I would assume some type of bubbling is causing the two click events (one on the body, one of the select box) to endlessly fire each other.
SimonC said:
@karl – Thanks for the tip dude, I was trying to work out the difference in why arc90’s example was working and mine wasn’t then I discovered it was the jQuery version. Your tip solved it, many thanks for saving me a while in debugging.
Jeff cook said:
Neat tool! Thanks. It doesn’t appear to support the select SIZE attribute, though. That is somewhat problematic for longer select lists. . .
Jeff Cook said:
For those asking how to get selected options, here’s a function I wrote to do just that. Pass in the original SELECT ID. . .
function readMultiSelectInfo(ID) {
var ID_Selected=ID+’=';
var p=0;
while (document.getElementById(‘multiSelect-options-’+ID+’-'+p)) {
if (document.getElementById(‘multiSelect-options-’+ID+’-'+p).checked) {
if (ID_Selected!=ID+’=') ID_Selected += ‘,’;
ID_Selected += document.getElementById(‘multiSelect-options-’+ID+’-'+p).value;
}
p++;
}
return ID_Selected
}
Go Media said:
Great script; If anyone has the problem with IE6 showing any select boxes underneath the multi-select layer showing through, just add this code inside the selectTitle.click function:
if(!select_state)
{
$(“#selectboxname”).css(“visibility”,”hidden”);
}
else
{
$(“#selectboxname”).css(“visibility”,”visible”);
}
You could use ‘display’ and ‘none’ / ‘display’ and ‘block’ instead. I reckon this could be expanded to get all select boxes beneath your multiselect, then loop through these and apply the code above.Just not had time to do it…
Chris Kilmer said:
The plugin is pretty cool. Provides a nice, understandable interface for building multi-selects.
I have a question. I need to be able to enable/disable the select box based on whether or not a checkbox is checked. With a standard select box, this is trivial. However, with this mutli-select, I don’t see an easy way to bind/unbind the selectTitle.click(function(){}) function.
Is there an easy way to do this? Would this be something that would be good to refactor into bind_events() or unbind_events() methods?
I’d be happy to contribute if you feel this might be the right direction to move in.
Thanks again for the great code.
Ben Sgro said:
Hello Chris et all,
I haven’t looked at this code in a long time – feel free to tinker with it and improve. I’ll be sure to update and provide credit.
Enjoy,
- Ben
VaN said:
Hi everyone,
that’s really a great code !
What I would like to do is quite simple i guess :
When selecting elements, I’d like the title being updated with the values selected : Here is an exemple of a prototype-based multiple select, doing what I want to do with this jQuery multiple select : http://livepipe.net/#image_2 (into select Multiple Tab).
Is there any way to make it work ?
Jeff Cook said:
Ben,
FYI – a minor bug:
line 450 of arc90_multiselect.js should have:
li:not(.a9selectall)
instead of
li:not(.selectall)
Jeff
VaN said:
Hello,
nice script, but I’m getting a stack overflow error, with IE 6 & 7.
I’m using jquery 1.3.2 with multiselect 1.1
I didn’t find anything about this, no-one had this problem before ?
How to solve it ?
VaN said:
If I switch to jquery 1.2.6, bug is solved.
Do you plan to fix that bug for jquery 1.3.2 ?
CC said:
I’m getting the same stack overflow error with jQuery 1.3.2… any fix yet?
Braunson said:
You can now add Chrome 2.0.172.28 to your Supported Browsers list now :)
Sean said:
IE8 also = stack overflow
Mark Steggles said:
Im getting stack overflow in IE7
and
too much recursion error in Firefox
Anyway to fix this for jquery 1.3.2?
Scott said:
@karl – thanks again for that code, much appreciated that someone found the bug AND posted the fix. Thanks!
Pooh said:
How can I get the data from multiselect?
Peter said:
@Eva:
I ran into the same bgIframe issue, and was able to fix it by including the bgiframe plugin JS just above multiselect, and adding the following code to the end of MultiSelectOptionsShow:
if ($.fn.bgiframe) {
$(‘.multiSelectOptions’).bgiframe();
}
Andrew said:
I removed the following rule from the CSS stylesheet:
.arc90_multiselect {
width: 12.5em;
height: 1.35em;
visibility: hidden;
}
The reason is that without JavaScript, the form element is hidden, which should only occur for users with JavaScript.
I then replaced this with the following, placed in a JavaScript snippet under the form:
$(‘.arc90_multiselect’).css({ ‘width’ : ‘12.5em’, ‘height’ : ‘1.35em’, ‘visibility’ : ‘hidden’});
Regards
Alessandro said:
@Andrew
is that a solution for the “stack overflow” bug with jquery 1.3.2?
DRK said:
First of all: Great script!
There is a little bug when showing more that one multiselect control in the same HTML form. Dropdown behaves funny and starts opening and closing the wrong control. That’s because the use of a couple of global variables (multiSelect_timer and select_state). I’ve transformed then into a couple of arrays and it started working fine!
Here’s the patch file:
http://www.drk.com.ar/files/mspatch
Luis Simoes said:
I have two questions:
1 – Is it possible to add scrollers if there are alot of items? Or even if their description is too big?
2 – How to make the dropdown list to appear aligned beneath the title? Like a regular dropdown or combobox.
Regards and Congratulations for the great and simple plugin