How to toggle selection of an option in a multi-se

2020-02-09 10:27发布

I have a standard select multiple HTML Input field, for example:

<select multiple="multiple" size="5" id="mysel" name="countries"> 
    <option value="2">Afghanistan</option> 
    <option value="4">Aland</option> 
</select>

As this is a multi-select, to select more than one value you have to hold the CTRL key and select any further elements. However what I want to achieve is, that:

  1. Clicking an UNSELECTED option SELECTs it
  2. Clicking a SELECTED option UNSELECTS it.

The idea is to avoid having to press the CTRL key and change the usage semantics of this input field. Elements should only be selectable and un-selectable by clicking (ie. toggling of the select status).

I have not yet been able to implement this. The pseudo-code should look something like this.

  1. Catch a Click event.
  2. Check if the element that was clicked was unselected, then select it
  3. Or if the element that was clicked was selected, then unselect it.

How should I implement this?

7条回答
不美不萌又怎样
2楼-- · 2020-02-09 11:03

I just tried this solution and the selected answer did not work for Jquery 1.9.1

The answer by Oscar looked much better but it mixed properties with attributes and doesnt work if you select, de-select then try to select again as it puts the select into an unusable state

I have found the correct answer for me was the following

$("select[multiple] option").mousedown(function () {
       if ($(this).prop("selected"))
           $(this).prop("selected", false);
       else
           $(this).prop("selected", true);
       return false;    });

I hope this helps others ;)

查看更多
Summer. ? 凉城
3楼-- · 2020-02-09 11:05

Another variant without JQuery:

var multiSelect = {};

function init() {      
  var s = document.getElementsByTagName('select');
  for (var i = 0; i < s.length; i++) {
    if (s[i].multiple) {
      var n = s[i].name;
      multiSelect[n] = [];
      for (var j = 0; j < s[i].options.length; j++) {
        multiSelect[n][j] = s[i].options[j].selected;
      }
      s[i].onclick = changeMultiSelect;
    }
  }
}

function changeMultiSelect() {
  var n = this.name;
  for (var i=0; i < this.options.length; i++) {
    if (this.options[i].selected) {
      multiSelect[n][i] = !multiSelect[n][i];
    }
    this.options[i].selected = multiSelect[n][i];
  }
}

window.onload = init;
查看更多
▲ chillily
4楼-- · 2020-02-09 11:11

Probably some fix coming with the new jQuery versions:

$("select[multiple] option").mousedown(function(){
    var $self = $(this);

    if ($self.attr("selected")){
        $self.removeAttr("selected");
    } else {
        $self.attr("selected", "selected");
    }
    return false;
});
查看更多
兄弟一词,经得起流年.
5楼-- · 2020-02-09 11:11

Using jquery 1.9.1 the javascript code is:

   $("select[multiple] option").mousedown(function () {
       var $self = $(this);
       if ($self.prop("selected"))
           $self.removeAttr("selected");
       else
           $self.attr("selected", "selected");
       return false;
   });
查看更多
兄弟一词,经得起流年.
6楼-- · 2020-02-09 11:17

You're right in wanting to change the default behaviour of select multiple input fields. They tend to contribute negatively towards user experience as the purpose is not clearly conveyed and users' may not understand how to use them correctly.

Re-purposing a multi-select box isn't right either. If you are considering using select multiple, then you might want to refactor your design. Perhaps you can use checkboxes instead?

Here's an article on the topic: http://www.ryancramer.com/journal/entries/select_multiple/

查看更多
▲ chillily
7楼-- · 2020-02-09 11:24

Javascript (without jquery):

var select = document.getElementById('mysel');
select.addEventListener('mousedown', function(e){
    var opt = e.target;
    if (opt.selected){
        opt.removeAttribute('selected');
        opt.selected = false;
    } else {
        opt.setAttribute('selected', '');
        opt.selected = true;
    }
    e.preventDefault();
});

I see most of the answers above are binding the event with the option instead of the select. If my select has 1000 options, then it will bind 1000 events, will it affect the performance?

Because of this I also decide not to bind my event in the option.

查看更多
登录 后发表回答