As I mentioned recently, there is a bug in Internet Explorer that stops you from disabling options in a select/dropdown element. At the time, I felt this was quite poor so I set about finding a solution. For the impatient among us, you can step straight to implementing it if you want.
Unsuccessful Ideas
In an attempt to save everyone else some time, I’m going to list the different ideas, methods and combinations of, I attempted that were unsuccessful:
- Attempt: use the CSS pseudo
:hover
against the <option> element.
Problem: Internet Explorer doesn’t support the :hover
pseudo class on arbitrary elements.
- Attempt: Wrap the contents of the <option> element in an anchor and use the
:hover
on that instead.
Problem: The <select> tag is considered a replaced element, which means the tag is replaced with your operating systems equivalent. As a by product, no other HTML element is valid within the <option> tag.
- Attempt: Use the JavaScript
onmouseover
and onmouseout
events on the <option> element to make the element appear as though it was disabled.
Problem: Internet Explorer doesn’t support the onmouseover
and onmouseout
events against an <option> element.
- Attempt: Use the JavaScript
onclick
event on the <option> element to check if the disabled
attribute has been applied, act accordingly if it has been.
Problem: Again, Internet Explorer doesn’t support the onclick
event againt the <option> element.
- Attempt: Use the JavaScript
onclick
event against the <select> element, to again check if an <option> has the disabled
attribute in use.
Problem: Internet Explorer doesn’t support the onclick
event against a <select> element.
Successful Ideas
The solution to this problem is comprised of two parts. Firstly, knowing when you make a selection or change the current selection. Secondly, keeping track of the current selection, so you can revert to it in case the user selects a disabled option in the list. If those two things can be achived, then we can emulate the disabled
attribute on an option
element
Part 1
You can get around not having an onclick
event against the option
element by using an onchange
event against the select
. Knowing when you click an option is mandatory, as it lets you know when/if to check that the selected option is disabled. This is taken care of, we can move on.
Part 2
Next up is keeping track of the ‘currently selected’ item. Generally, the first tool in the chest that most people reach for in this case is an onclick
event. However, since we’re working with a browser that doesn’t implement those events on the element(s) in question, another solution was needed. The next event that would match what we want to do is onselect
, however it isn’t implemented in IE either. Thankfully, the onfocus
event is our savior.
How It Works
First thing is making sure that the code only executes on the correct browsers. You could use browser sniffing techniques or proprietary JavaScript functions to isolate IE, however that can be inconsistent. Since we’re targeting IE, it seems more than reasonable to use a conditional comment. In case you are unfamiliar with them, a conditional comment looks like a standard HTML comment to every non-IE browser; however IE interprets them and allows the author very simple conditional testing. We’re going to use this simple testing to include an external JavaScript file.
If the JavaScript does execute, it checks to see if you have any <select> elements in the page. If you do, it iterates through them, attaching an onchange
and an onfocus
event to each one. At the same time, the disabled option elements (if there are any) are also highlighted with the disabled text colour.
At this point, you have nothing else to do. The onload
event and the two functions will do everything for you from this point. The one caveat is if you are manipulating the disabled
attributes on the options through the DOM. In which case, you do have to call the emulate
function, passing into it a reference the <select> you are manipulating.
The JavaScript
To make this work, an event and two functions are used. They are listed here so you can glance over them:
window.onload = function() {
if (document.getElementsByTagName) {
var s = document.getElementsByTagName("select");
if (s.length > 0) {
window.select_current = new Array();
for (var i=0, select; select = s[i]; i++) {
select.onfocus = function(){ window.select_current[this.id] = this.selectedIndex; }
select.onchange = function(){ restore(this); }
emulate(select);
}
}
}
}
The restore
function returns the selected item to its previous selection, if the newly selected item is disabled.
function restore(e) {
if (e.options[e.selectedIndex].disabled) {
e.selectedIndex = window.select_current[e.id];
}
}
The emulate
function changes the font colour of all options in a <select> element with the disabled
attribute set. The colours used on lines 4 and 7 are CSS2 colour names, which are considered system colours. System colours reflect what your current computer settings are, so they should change with your current desktop theme (at least that is my interpretation of it).
function emulate(e) {
for (var i=0, option; option = e.options[i]; i++) {
if (option.disabled) {
option.style.color = "graytext";
}
else {
option.style.color = "menutext";
}
}
}
Implementing
Using this script is meant to be as simple as possible. All you have to do is download the external JavaScript file. Upload it to your site and place a single conditional comment in your HTML, such as:
<!--[if lt IE 7]>
<script type="text/javascript" src="select-option-disabled-emulation.js"></script>
<![endif]-->
Examples
Following are some simple examples to display what Internet Explorer renders at the moment, through either html/xhtml/quirk/compliant states. There are also two examples of how the script functions as well, simple but they demonstrate it none the less.
- HTML
- HTML Using JavaScript
Follow Up
After this post being active for over a year now, it continues to draw in consistent traffic from around the internet. Even though this was a proof of concept and not a complete solution, it has saved many people a lot of time. Plenty of people have taken the basic idea I started with and extended it, which I think is fantastic. Recently, a couple of people have sent through comprehensive techniques which are either built on my initial work in some way or inspired by it. These solutions are out perform my simple proof of concept, so they are definitely worth noting for everyone to use:
- Apptaro created an elegant solution using a DHTML Behaviour file. These behaviour files only execute in Internet Explorer which is a great way isolating it from interfering with other web browsers.
- Kaleb Walton has implemented a JavaScript object oriented version of my proof of concept. Kaleb’s version implements the fix for a standard dropdown, a listbox and a multi-select listbox.
Both of the above examples are excellent, so you should pick which ever you feel is best going to suit your needs.