Andy C
Andy C

Reputation: 119

Unable to deselect 'select multiple' options with selection counter and optgroups

I'm using the code from the accepted answer here

How do you limit options selected in a html select box?

to count the selected options in a 'select multiple' menu:

var last_valid_selection = null;    
$("#select_options").change(function(event) {
    if ($(this).val().length > 10) {
        $(this).val(last_valid_selection);
    } else {
          last_valid_selection = $(this).val();
          $("#select_options_text").text("Please select at least one, and up to ten options. You have currently selected "+$(this).val().length); 
    }     
});

The menu is divided into six optgroups. When I hit 10 selections I can no longer make selections, as expected. But I can also no longer use CTRL+click on selected options to deselect them.

If I remove all optgroups, the menu functions correctly. It also functions correctly with one and two optgroups. It only seems to be when a third optgroup is added that the problem described above appears.

I have tested in Chrome and Firefox and the problem occurs in both.

Upvotes: 2

Views: 712

Answers (1)

alan0xd7
alan0xd7

Reputation: 1851

Problem

You have duplicate options, so when try to restore the last selection by calling $(this).val(last_valid_selection), you could be selecting more than one value than you actually want (i.e. you end up selecting more than 10).

For example, you have more than one Biochemistry, so when last_valid_selection contains one instance of Biochemistry, all the duplicate Biochemistry options will be selected.

Solution

Use a different way of remembering the last valid selections.

Here I present a solution using data attribute and individually store whether or not an option has been previously selected.

function save_selected(select){
    $(select).find("option").each(function(){
        var t = $(this);
        t.data("last-selected", t.is(":selected"));
    });
};

function load_selected(select){
    $(select).find("option").each(function(){
        var t = $(this);
        t.attr("selected", t.data("last-selected"));
    });
};

$("#select_options").change(function(event) {
    if ($(this).val().length > 10) {
        load_selected(this);
    } else {
        save_selected(this);
    }
});

Using this method, each individual option element has its own "last selected" state stored in its own data attribute. There would be no duplicate conflicts.

Demo: https://jsfiddle.net/alan0xd7/gzdrL5wu/12/

Upvotes: 1

Related Questions