Naturally, a task as simple as adding and removing options to a select element in JavaScript turns out to be a 2 hour pain. Especially if you want to please a wide range of browsers. For my purposes, Prototype.js was the weapon, Insertion.After
was the ammo, and adding an option at any position in the drop down was the target. The first attempt was straightforward:
new Insertion.After(node, '<option> </option>');
In this case, node
is one of the options already in the select element, and the second parameter designates the markup to add after it. As expected, this worked great in Firefox and Safari. As I grudgingly opened Internet Explorer, I was bombarded with a wave of errors and an select element not functioning properly. It turns out the whole innerHTML
on a drop down doesn’t work out so well.
A bit of detective work led me to a bug report confirming the innerHTML
problem. In the spirit of removing any sort of browser detection, I decided to see how IE6 would like to handle things, and do it the hard way. Two options presented themselves:
el.add(optn, pos);
and
el.options.add(optn, pos);
I began with the second one, and was relieved to see it work in IE6. A click and a keystroke later, and Safari started breaking on me. Apparently the W3C recommends the add method be part of the actual select element, and not the options. So I tested the first approach, and it worked in IE6. Since it followed W3c recommendations, I figured I was set. But then Safari decided to always add the option to the end of the list, and Firefox yelled at me:
uncaught exception: [Exception… “Could not convert JavaScript argument” nsresult: “0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)”
Finally, I gave in and took the browser detection approach.
if(Prototype.Browser.IE) {
var optn = document.createElement("OPTION");
optn.text = ' ';
optn.value = ' ';
el.options.add(optn, pos);
}
else new Insertion.After(node, '<option> </option>');
Hi Ryan,
That’s been fixed in SVN trunk. If you’re running edge you can now write:
or:
(
Element#insert
defaults to bottom if no option is specified.)This syntax will replace
new Insertion...
in the next Prototype release (which will be kept for backwards compatibility).Yeah, I’ve run into this one on more than one occasion. After a period of time, I tend to forget, and run into it again.
Good to see that the fantastic libraries out there are handling more and more of this bllx for us.
Thanks for the heads up, Tobie. I’m with Morgan — it’s good to know there are people a lot smarter than I am staying on top of this stuff.
Hi Ryan, I am a bit confused with the usage of ‘el.options’. Is ‘el’ the resultant of something like $(‘someElement’)? Then what is options method? Thanks.
Found this piece of code somewhere in the archive:
Quite odd, but it works (looks like the null pos param is messing things up in IE) although it can’t be used to insert elements anywhere but at the end. Maybe I should revise it and use your code ;-)
@ Tobie: thanks for the info :-)
@ Subbu: el is the element indeed retrieved by document.getElementById() (or the prototype $() shorthand). “.options” is a property of that element. (TIP: do a $(‘yourList’); in the FireBug console and click on the result to browse its properties and methods ;-))
@Bramus!: Thanks a lot :)
Why not simply use Prototype’s Ajax.Updater() and [re]load a complete SELECT options list all at once into a DIV tag set?