35

Okay having a bit of trouble here, wanted to disable some of the options when selecting a radio. When ABC is selected disable the 1,2 & 3 options, etc...

$("input:radio[@name='abc123']").click(function() {
   if($(this).val() == 'abc') {

      // Disable 
      $("'theOptions' option[value='1']").attr("disabled","disabled");
      $("'theOptions' option[value='2']").attr("disabled","disabled");
      $("'theOptions' option[value='3']").attr("disabled","disabled");

   } else {
      // Disbale abc's
   }    
});

ABC: <input type="radio" name="abc123" id="abc"/>
123: <input type="radio" name="abc123" id="123"/>

<select id="theOptions">
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="a">a</option>
  <option value="b">b</option>
  <option value="c">c</option>
</select>

Not working any ideas?

UPDATE:

Ok I got the enable/disable working but a new problem has arose. The disabled options for my select box only work in FF and IE8. I have tested IE6 and the disabled is not working. I have tried to use the hide() and show() with no luck either. basically I need to hide/disable/remove the options (for all browsers) and be able to add them back if the other radio option is selected and vice versa.

CONCLUSION:

Thanks for all the solutions, most of all of them answered my original question. Much PROPS to all :)

Phill Pafford
  • 83,471
  • 91
  • 263
  • 383
  • A solution to this problem: http://stackoverflow.com/questions/7553880/ipad-disable-select-options-w-o-jquery/9914179#9914179 – standup75 Mar 28 '12 at 19:15

8 Answers8

74

The proper way to achieve the functionality you want is just to remove the options. As you discovered the hard way, disabling individual options is not supported particularly well across browsers. I just woke up and feel like programming something so I whipped up a small plugin to easily filter a select based on a radio's selected ID attribute. Although the rest of the solutions will get the job done, if you are planning on doing this throughout your app this should help. If not, then I guess it's for anyone else that stumbles upon this. Here is the plugin code you could stash away somewhere:

jQuery.fn.filterOn = function(radio, values) {
    return this.each(function() {
        var select = this;
        var options = [];
        $(select).find('option').each(function() {
            options.push({value: $(this).val(), text: $(this).text()});
        });
        $(select).data('options', options);
        $(radio).click(function() {
            var options = $(select).empty().data('options');
            var haystack = values[$(this).attr('id')];
            $.each(options, function(i) {
                var option = options[i];
                if($.inArray(option.value, haystack) !== -1) {
                    $(select).append(
                    $('<option>').text(option.text).val(option.value)
                    );
                }
            });
        });            
    });
};

And here is how to use it:

$(function() {
    $('#theOptions').filterOn('input:radio[name=abc123]', {
        'abc': ['a','b','c'],
        '123': ['1','2','3']        
    });
});

The first argument is a selector for the radio group, the second a dictionary where the keys are the radio ID to match, and the value is an array of what select option values should remain. There's a lot of things that could be done to abstract this further, let me know if you are interested and I could certainly do that.

Here is a demo of it in action.

EDIT: Also, forgot to add, according to the jQuery documentation:

In jQuery 1.3 [@attr] style selectors were removed (they were previously deprecated in jQuery 1.2). Simply remove the '@' symbol from your selectors in order to make them work again.

Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
  • This is exactly what I need, Thanks a ton!!! One last question, does this go inside the document.ready or outside of it? – Phill Pafford May 18 '09 at 15:54
  • 2
    The plugin code can go outside of it, as long as it goes after jQuery is included. The code that calls it should go inside document ready as I have it or at the bottom of the document. – Paolo Bergantino May 18 '09 at 15:59
  • Thanks. Okay Last thing. I used a example as part of my code so the RegEx isnt working as expected. I have four values for the opiotns: BGE BGE_KKI OKE MYF And my Radio's are P and S I'm trying this but no luck: 'P': /('BGE'|'BGE_KKI'|'OKE')/, 'S': /('MYF')/ – Phill Pafford May 18 '09 at 16:21
  • 2
    You want to get rid of the single quotes around the letters and it should work, ie: (BGE|BGE_KKI|OKE) – Paolo Bergantino May 18 '09 at 16:33
  • 1
    By the way, if all you ever expect to want to match is something like a group of individual values, it would probably be cleanest to pass it as an array, like, 'P': ['BGE','BGE_KKI','OKE'] - if you are interested in this, I can modify the plugin for it. – Paolo Bergantino May 18 '09 at 16:34
  • Yes please :) and thanks for the other post. I think it's working the way I expected. – Phill Pafford May 18 '09 at 16:45
  • I updated the code to work with arrays instead of regular expressions. – Paolo Bergantino May 18 '09 at 16:56
  • Can I do this onload instead of click? the option will be selected onload – Phill Pafford May 20 '09 at 20:54
  • @Paolo Bergantino, I just used your code and its been a great help +1 – Luke Jun 30 '10 at 13:33
  • @Paolo Although I didn't use this exact code, I was able to change it to fit my needs. Thanks for putting this together. – Kevin Crowell Sep 21 '10 at 18:38
  • @Paolo how would you do it if the check boxes were drop downs? – say Jan 22 '11 at 11:00
  • @PaoloBergantino If I wanted to use select boxes rather than radio buttons is it just a case of changing `input:radio` to `input:select` in the function? – Vince P Mar 27 '12 at 09:31
17

You want something like this - Example Code here

$(function() {

$("input:radio[@name='abc123']").click(function() {
   if($(this).attr('id') == 'abc') {

      // Disable 123 and Enable abc
      $("#theOptions option[value='1']").attr("disabled","disabled");
      $("#theOptions option[value='2']").attr("disabled","disabled");
      $("#theOptions option[value='3']").attr("disabled","disabled");
      $("#theOptions option[value='a']").attr("selected","selected");
      $("#theOptions option[value='a']").attr("disabled","");
      $("#theOptions option[value='b']").attr("disabled","");
      $("#theOptions option[value='c']").attr("disabled","");

   } else {
      // Disable abc's and Enable 123
      $("#theOptions option[value='a']").attr("disabled","disabled");
      $("#theOptions option[value='b']").attr("disabled","disabled");
      $("#theOptions option[value='c']").attr("disabled","disabled");
      $("#theOptions option[value='1']").attr("selected","selected");          
      $("#theOptions option[value='1']").attr("disabled","");   
      $("#theOptions option[value='2']").attr("disabled","");
      $("#theOptions option[value='3']").attr("disabled","");

   }    
});

});

EDIT:

Improved version of the code, using regular expression to filter options based on option values. Working example here. You can edit the example by adding /edit to the URL

$(function() {

    $("input:radio[@name='abc123']").click(function() {

        // get the id of the selected radio
        var radio = $(this).attr('id'); 

        // set variables based on value of radio
        var regexDisabled = radio == 'abc' ?  /[1-3]/ : /[a-c]/;      
        var regexEnabled = radio == 'abc' ? /[a-c]/ : /[1-3]/;
        var selection = radio == 'abc' ? 'a' : 1;

        // select all option elements who are children of id #theOptions
        $("#theOptions option")
            // filter the option elements to only those we want to disable
            .filter( function() { return this.value.match(regexDisabled);})
            // disable them
            .attr("disabled","disabled")
            // return to the previous wrapped set i.e. all option elements
            .end()
            // and filter to those option elements we want to enable
            .filter( function() { return this.value.match(regexEnabled);})
            // enable them
            .attr("disabled","");
       // change the selected option element in the dropdown
       $("#theOptions option[value='" + selection + "']").attr("selected","selected");

    });

});

EDIT 2:

Since the disabled attribute doesn't appear to work reliably across browsers, I think your only option is to remove the option elements not needed when a radio button is selected. Working Example here

  $(function() {

        $("input:radio[@name='abc123']").click(function() {

            // store the option elements in an array
            var options = [];
            options[0] = '<option value="1">1</option>';
            options[1] = '<option value="2">2</option>';
            options[2] = '<option value="3">3</option>';
            options[3] = '<option value="a">a</option>';
            options[4] = '<option value="b">b</option>';
            options[5] = '<option value="c">c</option>';


            var radio = $(this).attr('id');   
            var regexEnabled = radio == 'abc' ? /[a-c]/ : /[1-3]/;

            // set the option elements in #theOptions to those that match the regular expression
            $("#theOptions").html(
            $(options.join(''))
                // filter the option elements to only those we want to include in the dropdown
                .filter( function() { return this.value.match(regexEnabled);})
            );


        });

    });

or even

  $(function() {

        // get the child elements of the dropdown when the DOM has loaded
        var options = $("#theOptions").children('option');

        $("input:radio[@name='abc123']").click(function() {         

            var radio = $(this).attr('id');   
            var regexEnabled = radio == 'abc' ? /[a-c]/ : /[1-3]/;

            // set the option elements in #theOptions to those that match the regular expression
            $("#theOptions").html(
            $(options)
                // filter the option elements to only those we want to include in the dropdown
                .filter( function() { return this.value.match(regexEnabled);})
            );

        }); 
    });
Russ Cam
  • 124,184
  • 33
  • 204
  • 266
  • Another issue, YIKES! Look at the original problem + EDIT. Thanks :) – Phill Pafford May 18 '09 at 14:24
  • I'm trying this but how do I add the removed elements when selecting the other option (Like toggle back and forth). Also how do I check for duplicates? Thanks again for all the help in this issue. – Phill Pafford May 18 '09 at 15:05
  • That's handled by the regex matching, either against the option elements in an array (penultimate code example), or against option elements captured in a variable when the DOM has loaded (final code example). – Russ Cam May 18 '09 at 15:29
  • This looks like the best solution but due to the browser issue it just doesn't work for me. Thanks for the efforts – Phill Pafford May 18 '09 at 16:23
  • the option element appending will work cross browser but Paolo's got the right idea in wrapping the functionality in a plugin – Russ Cam May 18 '09 at 17:27
3

the first problem is with

$(this).val()

replace it with

$(this).attr('id') == 'abc'

then this will not work

$("'theOptions'..")

use

$("#theOptions option[value='1']").attr('disabled','disabled') //to disable
$("#theOptions option[value='a']").attr('disabled','') //to ENABLE
TheVillageIdiot
  • 40,053
  • 20
  • 133
  • 188
  • This is working but one follow up question. How do I select an ENABLED option? – Phill Pafford May 18 '09 at 12:54
  • Phill if you mean how do you enable option the the last line (ending with comment //to Enable) do the trick. If otherwise then I don't understand :( – TheVillageIdiot May 18 '09 at 13:18
  • I saw that, but what I wanted was to select one of the enable options in the dropdown. when disabling the options the option that is selected is still enabled even if it has been disabled, until you select an enabled option. then you can't select it again. Sorry does this make sense? so If I disable the abs's and the option is pre-selected on the a the a is still enabled until I re-select a new enabled option. – Phill Pafford May 18 '09 at 13:55
  • Kool thanks let me give that a try. Another problem has been brought to light. Please read the Edited version of the original problem. BTW thanks for all the help and feedback much props :) – Phill Pafford May 18 '09 at 14:23
1

which browser are you using? I've never used it before but it seems to be unsupported in IE before IE8. See this link for more information:

http://www.w3schools.com/TAGS/att_option_disabled.asp

Temple
  • 1,079
  • 1
  • 10
  • 22
0

just fix the selector $("'theOptions' option[value='1']") to $("#theOptions option[value='1']") and everything will work fine

Raptor
  • 53,206
  • 45
  • 230
  • 366
jamil
  • 127
  • 7
0

Your selector is wrong. Instead of

$("'theOptions' option[value='1']")

you should use

$("#theOptions > option[value='1']")

See also the jQuery selectors documentation. And take a look at the suggestion by aman.tur.

Community
  • 1
  • 1
Ronald Wildenberg
  • 31,634
  • 14
  • 90
  • 133
0

If you want to disable some options, than the code below should work

$("input:radio[name='abc123']").click(function() {
   var value = $(this).val();

   $("option[value='1'], option[value='2'], option[value='3']", "#theOptions").each(function(){
      this.disabled = value == 'abc';
   });
   $("option[value='a'], option[value='b'], option[value='c']", "#theOptions").each(function(){
      this.disabled = value == '123';
   })
});

and the radio-buttons

ABC: <input type="radio" name="abc123" value="abc" id="abc"/>
123: <input type="radio" name="abc123" value="123" id="123"/>

If you want to remove the options from select list, than use this code

$(function(){
   var options = null;
   $("input:radio[name='abc123']").click(function() {
      var value = $(this).val();
      if(options != null)options.appendTo('#theOptions');
      if(value == 'abc' )
         options = $("option[value='1'], option[value='2'], option[value='3']", "#theOptions").remove();
      else if(value == '123')
         options = $("option[value='a'], option[value='b'], option[value='c']", "#theOptions").remove();
   });
});

BTW. my code uses current stable release of jQuery (1.3.2). If you are using older release, you will need to change the attribute selectors to old syntax.

option[value='1'] to option[@value='1']

Rafael
  • 18,349
  • 5
  • 58
  • 67
  • Another issue, YIKES! Look at the original problem + EDIT. Thanks :) – Phill Pafford May 18 '09 at 14:25
  • Edited my whole post. Look at the new code samples. Now, it should work properly. – Rafael May 18 '09 at 14:55
  • Looks good but now how do I add the removed options if the use selects the other radio option as well as handling duplicates. Thanks again for the help on this :) – Phill Pafford May 18 '09 at 15:23
  • My code inserts all removed options again with if(options != null)options.appendTo('#theOptions');). After re-inserting the options, it checks what radio button is selected and removes other options. There shouldn't also occur any duplicates. If I did understand your question wrong, please try to explain it in other words, maybe then I'll be able to help more. – Rafael May 18 '09 at 15:51
0
$(":radio[name=abc123]").click(function() {
   var $options = $("#theOptions")
   var toggle = ($(this).val() == 'abc') ? true : false;

   $("[value=1],[value=2],[value=3]", $options).attr("disabled", toggle);
   $("[value=a],[value=b],[value=c]", $options).attr("disabled", !toggle);
});
duckyflip
  • 16,189
  • 5
  • 33
  • 36