How can I get the last selected value in a ListBox

2019-05-17 11:13发布

问题:

I have a listbox and I must limit its selection up to 5 items. If a 6th item is selected, I want to "deselect" it.

But, I'm having some problems on finding the last selected item and "deselect" it. And the last item selected it's necessary the $("#mySelect option:last")...

How can I get the selected item of a listbox??

Thanks!!!

回答1:

This will do it, although there is a brief "flash" of selection (you might want ot have a <span> show up underneath the <select> to say something like Maximum selection reached).

$('#mySelect').click(function(e) {
  if ($('option:selected',this).length > 5) {    
     $(e.target).removeAttr('selected');  
  }
});

I'll leave it as an exercise for you to get it working with keyboard selectivity too.

Here's a Working Demo

EDIT:

Ok, I'll admit that this is not the first time that I have been stung by also not testing an answer in IE too (there seem to be a lot of problems with <select> elements in IE), but here is a flexible solution that I have tested in IE 6 and Firefox 3.5.3 and it works in both. I've wrapped it in a plugin, in case you need this on more than one page

(function($) {

$.fn.maxLimitSelect = function(max) {

  if (!max || !/^\d+$/.test(max)) return this;

  return this.each(function() {

    $(this).bind("click change keypress",{ max: max },function(event) {

      var options = $('option', this);
      var max = event.data.max;
      var selected = $('option:selected', this);
      var indexes;

      if (selected.length === max) {  
       indexes = $.map(options, function(e, i) { 
                   if(e.selected) return i; 
                 }); 
       $.data(this, "indexes", indexes);
      }
      else if (selected.length > max) {
       indexes = $.data(this, "indexes");
       options
         .removeAttr('selected')
         .each(function() { 
           var $this = $(this);
           if ($.inArray($this.prevAll().length, indexes) !== -1) {  
             $this.attr('selected','selected');
           }
         });   
      } 
    });
  });
}

})(jQuery);

Then to use, it's simply

$('#mySelect').maxLimitSelect(5);

passing in the maximum number of items that can be selected. This works with key and mouse selections in both IE and Firefox versions tested although interestingly, IE 6 doesn't appear to support the Ctrl hold and Space to select multiple items, but does allow holding Shift to select a number of contiguous items. The plugin does limit this to the passed in max.

Here's a Working Demo



回答2:

the :last part of your selector will select the "last" physical item in the select list (it doesn't relate to whether it is selected or not).

AFAIK, you need to iterate over the options, and test if each is selected (to get your count) or use the :selected pseudo selector.

//Or as noted by @peirix you can try to get it with :selected.
//Note that this will just clear the last (by rendered order) selection...
//not the "last" option that was selected.

if($("#mySelect option:selected").size() >= 6){
  $("#mySelect option:selected:last").attr('selected', null);
}

UPDATE:

Wow, this was more complex than I thought!... below is a tested example that works... it could likely be cleaner, but I'll leave that to others to hack ;-)

<script>
  $('#mySelect').bind('change', function(){
    if($("#mySelect option:selected").size() == 5){
      //5 picked, (re)store them...
      var sel = [];
      $("#mySelect option").each(function(i){
        if($(this).attr('selected')){
          sel[i] = true;
        } else {
          sel[i] = false;
        }
      });
      $(this).data('selectedIndexes',sel);
    } else if($("#mySelect option:selected").size() >= 6){
      //too many reset to orig...
      $("#mySelect option").each(function(i){
        if($(this).parent().data('selectedIndexes')[i]){
          $(this).attr('selected', 'selected');
        } else {
          $(this).attr('selected', '');
        }
      });
    }
  });
</script>

sample HTML:

<select id="mySelect" multiple="multiple" size="12">
  <option value="a">aaaaaaaaaaaa</option>
  <option value="b">bbbbbbbbbbbb</option>
  <option value="c">cccccccccccc</option>
  <option value="d">dddddddddddd</option>
  <option value="e">eeeeeeeeeeee</option>
  <option value="f">ffffffffffff</option>
  <option value="g">gggggggggggg</option>
  <option value="h">hhhhhhhhhhhh</option>
  <option value="i">iiiiiiiiiiii</option>
  <option value="j">jjjjjjjjjjjj</option>
  <option value="k">kkkkkkkkkkkk</option>
  <option value="l">llllllllllll</option>
</select>


回答3:

This will basically listen for any options that get clicked. If one gets clicked, the script checks to see how many total options are selected (including the one just clicked on). If the number of selected options is more than 5, the most-recently-clicked item will become "deselected".

$("#mySelect").click(function() {
    var num_selected = $('#mySelect option:selected').length;
    if(num_selected > 5) {
        $(e.target).removeAttr('selected');
    }
});

If you'd like to let people know why their option just became deselected, you can do this:

$("#mySelect").click(function(e) {
    var num_selected = $('#mySelect option:selected').length;
    if(num_selected > 5) {
        $(e.target).removeAttr('selected');
        alert('You are limited to 5 options at a time...');
    }
});

Hope that works out for you. This code was inspired by peirix.



回答4:

Do you have to get the last one? Can't you just count how many are selected and then prevent further selections?

This function will check that the given SELECT element contains fewer than 'maximum' selected options.

function checkLimits( list, maximum ) {
    var options = list.options;
    var size = options.length;
    var numSelected = 0;

    for( var i = 0; i < size; ++i ) {
        if( options[ i ].selected ) ++numSelected;
    }
    if( numSelected > maximum ) {
        alert( 'You have selected more than ' + maximum + ' options.\n' +
            'Please deselect ' + ( numSelected - maximum ) + ' option(s) then
            try again.' );
        return false;
    }
    return true;
}

To call it directly from a form's onsubmit event, you could do:

<select ... onsubmit="return checkLimits(this.listName, 2)">

You could jQueryify it, but this should get you started. Taken from http://bytes.com/topic/javascript/answers/93760-please-help-limit-number-selections-multiple-select-list-box#post316514



回答5:

This should do the trick:

$("#mySelect option:checked:last").val(); //or not

A small re-write of Cory Larson's answer:

$("#mySelect option").mousedown(function() {
   if ($("#mySelect :checked").length > 5) {
      return false;
   }
   return true;
});

This will just not let the user check another option when the maximum number has been reached. And you could probably write out something to the user explaining that the maximum number has been reached.



回答6:

This seems to work on a little test page I did:

$('#mySelect option:selected:gt(4)').removeAttr('selected')


回答7:

$('#mySelect option:selected').length; doesn't seem to work on IE. Works well in Chrome though.