treehouse : what would you like to learn today?
Web Design Web Development iOS Development

[Solved] Need help with disabling select box options

  • Anyone with any JavaScript/jQuery experience? Need some help...

    I'm putting together a page that will be used for an account creation process. As part of it, the user has to pick three security questions and provide answers. So, on the page there's three identical select boxes with the same set of questions to choose from.

    Now, the issue is that we don't want the user to be able to pick the same question multiple times. So, we've put together the following script (with the help of a tutorial we found online). When the user selects a question from one of the menus, that same question is disabled in the other two menus.

    Here's what we have so far:



    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8" />
    <title>Select Box Filtering</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"></script&gt;
    <script type="text/javascript">
    $(document).ready(function(){
    $('.question').change(function(){
    $('.question option:selected').each(function(){
    optionIndex = $(this).index();
    if (optionIndex > 0){
    $('.question').each(function(){
    $(this).children('option').eq(optionIndex).not(':selected').attr('disabled', 'disabled');
    });
    }
    });
    });
    });
    </script>
    </head>
    <body>
    <select class="question">
    <option value="0">Choose a question...</option>
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
    <option value="4">Option 4</option>
    <option value="5">Option 5</option>
    </select>
    <select class="question">
    <option value="0">Choose a question...</option>
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
    <option value="4">Option 4</option>
    <option value="5">Option 5</option>
    </select>
    <select class="question">
    <option value="0">Choose a question...</option>
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
    <option value="4">Option 4</option>
    <option value="5">Option 5</option>
    </select>
    </body>
    </html>



    That works fine, but there's one issue - if the user changes any of the questions that they picked, such that one that they chose earlier is no longer used, it remains disabled even though it shouldn't be. In other words, say the user chooses Option 1 from the first menu (which then disables Option 1 in the second and third menus). If they then change their selection in the first menu to Option 2, then Option 1 should reenable in the second and third menus since it's no longer selected anywhere.

    So, I need to write a function that checks to see if an option is disabled but not selected across all three menus, and if so, then reenable it. I just have no idea how.

    If anyone has any insight, or knows of a better way to do this, please let me know!
  • This could be a little cleaner, like storing the $('.question') in a variable and whatnot, plus I don't particularly like hard-coding '.question' everywhere, but here:


    // This function should return an array of the value properties of all the selected options
    function getSelectedValues() {
    // Initialize an empty array to store the values
    var selectedValues = []
    // grab all the selected option elements and store them in a variable
    , $selected = $('.question').children('option:selected');

    $selected.each(function(){
    // this = the selected element. this.value = the value property
    // the push method adds its argument to the end of an array
    selectedValues.push(this.value);
    });

    // Send the results out into the ether
    return selectedValues;
    }

    // This grabs all the disabled options and changes their disabled property to the empty string
    function clearDisabled() {
    $('.question').children(':disabled').attr('disabled', '');
    }

    // This function disables all the options that are in the array it gets passed
    function disableSelected(selectedValues) {
    // This probably wasn't necessary, but it's good practice to build things like this into your code in case you reuse it in ways you didn't expect. You could add a different default value
    sv = selectedValues || [];

    // For each value in the array, we get all the options whose value is the same as that value, but filter out the one that is actually selected
    // Then we change those elements to disabled
    for (var i=0;i<sv.length;i++) {
    $('.question').children('option[value=' + sv[i] + ']').not(':selected').attr('disabled', 'disabled');
    }
    }

    $(document).ready(function(){
    // OK, the DOM is ready to manipulate, so let's call all those functions we just assigned:
    // When any of the selects change, do some stuff:
    $('.question').change(function(){
    // First find all the values that have been selected, and store them as an array
    selectedValues = getSelectedValues();
    // Then make all the options enabled
    clearDisabled();
    // Then pass the selected values we got earlier to the function that disables those values everywhere they are not selected
    disableSelected(selectedValues);
    });

    });


    Get all the values that are selected, then enable all the options, then disable all the options that are selected.
  • Will have to test this some more, but so far, it looks like...IT WORKS! Dude, you are a lifesaver! Seriously, thank you so much!

    Could you explain a little more about how this works? Just for my own reference...
  • Updated the code to include explanatory comments. I might have over-explained, but I figured it was better than under-explaining...
  • Fantastic! Can I buy you a beer? :-)

    I was trying to think of ways I could "track" which options had to be reenabled, but that whole line of thinking was too complex and I couldn't get it to work. Your method is brilliant - just reset everything to enabled first, and THEN disable the selected options. Now that I've seen it, it makes perfect sense.

    Can I credit you in the code somehow when I use this in my project? You really helped me out a lot.
  • Such high praise... You can credit me if you want. Is there a PM thing here? ...Yeah, there we go. I'll give you my name and website, though there's not anything there right now.

    And you can buy me a beer next time you're in the city.
  • Really very nice demo..It helped me alot in my coding

    Thanku so much.....!!!