Disabling HTML <option>s
If browsers worked as they should it would be pretty simple to disable some of the options in a select list:
<select>
<option>Enabled</option>
<option disabled>Disabled</option>
</select>
Of course IE doesn't support this part of the spec, and it's not included in the IE 7 beta, so it's unlikely it will be supported in the near future. So, one option that makes IE behave similarly to the disabled options is to replace them with <optgroup> tags. The <optgroup>s cannot be selected and with a little CSS they look like disabled options. However, the static solution suggested didn't work for me since I needed to be able to disable or enable options at runtime. So, with a little JavaScript (and the help of MochiKit's DOM functions) the options can be enabled or disabled dynamically:
var selectStyleDisabled = function(select) {
forEach(select.options, function(opt) {
if (opt.disabled) {
var optgroup = OPTGROUP();
updateNodeAttributes(optgroup, {
label: opt.innerHTML,
style: { color: 'graytext' }});
optgroup._option = opt;
swapDOM(opt, optgroup);
}
});
forEach(select.getElementsByTagName("OPTGROUP"), function(optgroup) {
var option = optgroup._option;
if (option && !option.disabled) {
swapDOM(optgroup, option);
}
});
};
addLoadEvent(function() {
var selects = currentDocument().getElementsByTagName("SELECT");
forEach(selects, function(select) {
select._onfocus = select.onfocus;
select.onfocus = function() {
selectStyleDisabled(this);
if (this._onfocus)
return this._onfocus();
return true;
}
selectStyleDisabled(select);
});
});
The display of disabled options is updated in the "onfocus" method to make sure that changes in the disabled state of the options is reflected before the <select> is displayed again. Disabling options can be done directly to any of the option elements such as:
select.options[0].disabled = true;
However, a little care needs taken to re-enable options, since the <optgroup>s aren't in the "options" attribute of the <select>. The original option needs reenabled by accessing it through the "_option" attribute added to the <optgroup> element:
// reenable all disabled options in standards-compliant browsers
forEach(select.options, function(option) {
option.disabled = false;
});
// reenable all disabled options in IE
forEach(select.getElementsByTagName("OPTGROUP"), function(optgroup) {
optgroup._option.disabled = false;
});
To make sure that this IE hack only gets loaded in IE, put it in a .js file and wrap it in an IE conditional comment:
<!--if lt IE 8]>
<script type="text/javascript" src="select-ie-disabled-options.js"></script>
<![endif]-->