In Internet Explorer, the attribute "disabled" fails if used in tag option. See here a javascript to simulate the "disabled" attribute in Internet Explorer.
This code will execute and disable option in Standard browsers (FF, Op, etc):
<select> <option>opt 1</option> <option disabled="'disabled'">opt 2</option> <option>opt 3</option> </select>
In IE, it will fail.
The above code, simulates the attribute "disabled" to IE, using JavaScript. Try-it:
<!--[if lte IE 7]> <script> function ativaOptionsDisabled(){ var sels = document.getElementsByTagName('select'); for(var i=0; i < sels.length; i++){ sels[i].onchange= function(){ //pra se mudar pro desabilitado if(this.options[this.selectedIndex].disabled){ if(this.options.length<=1){ this.selectedIndex = -1; }else if(this.selectedIndex < this.options.length - 1){ this.selectedIndex++; }else{ this.selectedIndex--; } } } if(sels[i].options[sels[i].selectedIndex].disabled){ //se o selecionado atual é desabilitado chamo o onchange sels[i].onchange(); } for(var j=0; j < sels[i].options.length; j++){ //colocando o estilo if(sels[i].options[j].disabled){ sels[i].options[j].style.color = '#CCC'; } } } } window.attachEvent("onload", ativaOptionsDisabled) </script> <![endif]-->
Update: See other good solutions in comment box above too!
Ok. Now its just call this function in document load
<body onload='ativaOptionsDisabled()'>
Nice workaround, but the conditional comment around the function is incorrect.
ReplyDeleteThe 'disabled' attribute does not work in IE7 either (e.g. its still broken)
thus the logic should be applied to IE7 and below (presuming that MS fixes it in IE8)
cheers
steve
Oooo shit. heheh
ReplyDeleteBad IE, bad.
Thanks steve.
I'll update now.
I think that you should attach this function inside that conditional part, like:
ReplyDeleteSTART IF IE HERE
START SCRIPT HERE
function ativaOptionsDisabled()
{
//...
}
window.attachEvent('onload',ativaOptionsDisabled);
END OF SCRIPT HERE
END OF IF IE
What do you think? Now other browsers won't complain about missing function..
-Cursed
Yeah. Thanks anonymous.
ReplyDeleteThanks for the great workaround! I changed the function to the following in order to be more robust. Also, it fixes the assumption that the next option is not disabled:
ReplyDeleteif(this.options[this.selectedIndex].disabled){
var initial_index = this.selectedIndex
var found = false
while (this.selectedIndex < this.options.length - 1) {
this.selectedIndex++
if (!this.options[this.selectedIndex].disabled) {
found = true
break
}
}
if (!found) {
this.selectedIndex = initial_index
while (this.selectedIndex > 0) {
this.selectedIndex--
if (!this.options[this.selectedIndex].disabled) {
found = true
break
}
}
}
if (!found)
this.selectedIndex = -1
}
Thanks for contribute yunloh :)
ReplyDeleteGreat article, thanks a lot.
ReplyDeleteBut there's a little problem. For example, a select has 3 options: A, B and C. A is disabled. When users select C and then try to select A, B becomes selected.
Here's my workaround:
if (this.options[this.selectedIndex].disabled){
if (this.previousSelectedIndex !== undefined && !this.options[this.previousSelectedIndex].disabled) {
this.selectedIndex = this.previousSelectedIndex
} else {
var initial_index = this.selectedIndex
var found = false
while (this.selectedIndex < this.options.length - 1) {
this.selectedIndex++
if (!this.options[this.selectedIndex].disabled) {
found = true
break
}
}
if (!found) {
this.selectedIndex = initial_index
while (this.selectedIndex > 0) {
this.selectedIndex--
if (!this.options[this.selectedIndex].disabled) {
found = true
break
}
}
}
if (!found)
this.selectedIndex = -1
}
}
}
this.previousSelectedIndex = this.selectedIndex
So with the contribution on October 24, 2007 7:44 AM, what is the final JS funciton?
ReplyDeleteThank you.
Another workaround is to use optgroup for disabled options. Thats ok if they are permanently disabled.
ReplyDeleteI'd like to suggest you my workaround.
ReplyDeleteI had to disable those options dynamically + I'm already using onchange. Therefore I did this:
1. I had a variable for our fixIE function on the page start + enable/disable functions:
SCRIPT START
var fixIEFunction = function(object){return true;}; //this is a fuction for non-ie: it doesn't a thing
function disableElement(object) {
object.disabled = true;
object.style.color = "#CCC";
}
function enableElement(object) {
object.disabled = false;
object.style.color = "#000";
}
SCRIPT END
2. I placed our fixIE script at the end of the page:
--OUR IE CHECK--
SCRIPT START
fixIEFunction = function fixIEOnChange(object) {
if(object.options[object.selectedIndex].disabled && (object.oldValue!=null && object.oldValue!=undefined)){
object.selectedIndex = object.oldValue;
return false;
}
object.oldValue = object.selectedIndex;
return true;
}
SCRIPT END
--END IE CHECK--
In this script i override the function to act for IE.
3. Now we have to initialize our select.oldValue inside body.onload or whenever you want it to be. (You can do this someway else and also use those counting cyclic functions suggested before - but IE is also pretty slow with JS, so using property is faster).
for all selects on the page just do this:
select.oldValue = select.selectedIndex;
4. just run our function inside onChange handler:
function onChangeHandler(owner) {
if(fixIEFunction(owner)) {
//do something useful here
}
}
I want to put in another plug for Andreas Øverland's suggestion, the optgroup tag, which I initially overlooked. I never heard of the tag myself until today, and it might be the best workaround for some.
ReplyDelete<optgroup label="some text" > < optgroup >
It's intended to let your group options in a drop-down menu, like so.
< optgroup label="sandwiches" >
< option >PB&J</option >
< option >BLT</option >
</ optgroup >
To simulate a disabled option tag, don't put any options between the opening and closing optgroup tags. Use CSS if you want gray text.
Here are some links for more.
http://www.inquirium.net/blog/entry_157.php
http://reference.sitepoint.com/html/optgroup
http://msdn.microsoft.com/en-us/library/ms535876(VS.85).aspx
http://www.w3schools.com/tags/tag_optgroup.asp
And if this link wasn't posted for a javascript solution...
http://www.lattimore.id.au/2005/07/01/select-option-disabled-and-the-javascript-solution/
had some cut off links in my post above...Here are sniprurl versions.
ReplyDeletehttp://snipurl.com/2g797
Select, Option, Disabled And The JavaScript Solution « Post Archive « www.lattimore.id.au [www_lattimore_id_au]
http://snipurl.com/2g7a5
optGroup Object [msdn_microsoft_com]
Thanks michael, very good solution.
ReplyDeleteThanks very much! Saved my bacon in a crisis!
ReplyDeleteHi all...
ReplyDeleteI used this posted code in this page in my application and... when I chose only one item of combobox automatically its changed to other item not disabled near the item what I chose. OK. But before I have for example 3 or 4 items disabled near one of another its permitted select one item disabled again?!?! the code what I am posting work fine:
function conserta() {
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);
}
}
}
}
function restore(e) {
if (e.options[e.selectedIndex].disabled) {
e.selectedIndex = window.select_current[e.id];
}
}
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";
}
}
}
in body put conserta() in onload onption
(sorry about my bad english)
hugs...
Thanks.... updated it a little bit and it works like a charm. :)
ReplyDeleteMajor κῦδος to Micox and Dr4g0nF1y for the help! :^)
ReplyDeleteHi,
ReplyDeletethis IE bug really troubled me and that code above didn't work on me. I don't know why.
But then I made a small easy code which removes all non-selected and "disabled" options everytime user loads the page with IE. In other words, there is only one option to choose, the originally selected one.
Works like a charm now :)
Hey there!
ReplyDeleteNice work!
But I've git a problem.
I have three select boxes.
Your JavaScript only works with the first one.
What can I do?
Are you able to extend the script?
Maybe you can write a mail...
lukas.liebig@web.de
Thank you!
Bye, Lukas
Found a problem. If I have multiple disabled options in a row, it won't just to the next available option, but instead the one directly below it, which is supposed to be disabled.
ReplyDeleteThank you this is very usefull.
ReplyDeletejust tell my visitor not to use IE...
ReplyDeleteIE.. make me crazy...
wasting my time.. and money
hahhaa
thanks for the article anyway.. :)
Usando este código não funciona o onchange que tenho no select. Porque será ?
ReplyDeleteYour blog keeps getting better and better! Your older articles are not as good as newer ones you have a lot more creativity and originality now keep it up!
ReplyDeleteAmiable dispatch and this enter helped me alot in my college assignement. Gratefulness you as your information.
ReplyDeleteOpulently I acquiesce in but I contemplate the brief should prepare more info then it has.
ReplyDeleteNice dispatch and this post helped me alot in my college assignement. Thank you as your information.
ReplyDeleteWow, that all seems like an awful lot of code.
ReplyDeleteWouldn't it be simpler to just check for the disabled attribute, and if it returns true, send a return false? Like this.
select.onmousedown = function() {
var index = select.selectedIndex;
var option = select.options[index];
if(option.disabled==true) {return false;}
}
*lightning meta-CMS
Yes. You are correct.
ReplyDeleteThanks for contribution. :)
I'll use your solution.
Thanks a lot mate
ReplyDeleteGreat stuff, thanks for posting this. IE7 will hopefully be dead soon.
ReplyDeleteIf you know that you only have one item selected, get the 'select' element and pass it into the function below:
ReplyDeletefunction hideUnSelectedOptions(select)
{
var opts = select.options;
if (select != null)
{
while(opts.length > 1)
{
for (var i=0; i < opts.length; i++)
{
if(opts[i].selected == true)
{
opts[i].innerText;
}
else
{
opts[i] = null;
break;
}
}
}
}
}