Work around for onclick event of option tag

2019-08-07 05:36发布

问题:

I have a multi-select drop-down on my web page and a checkbox to allow user to select all items in the list.

<select id="itemsList" multiple="true" size="3"></select>
<input type="checkbox" id="bSelectAll" onclick="selectAllItems();" />Select all

Clicking the checkbox selects all items in the list. Now when I click on one of the items in the list, that item remains selected while everything else is deselected. I want exact opposite behavior. When an item is clicked, that item should get deselected while everything else should remain selected.

I know we can get this behavior by ctrl+clicking on an item. However, requirement is that it should happen on normal click.

I tried to check onclick of an option tag but it seems that it is not according to standards and hence supported by only a subset of browsers.

I could not accomplish this by using onclick and onchange events of select tag.

The behavior should be consistent when checkbox is not checked. In short clicking on an option tag should always toggle its selection.

This would be the default behavior if I use a list of checkboxes instead of select box. However, is there any way of doing this with what I have as of now?

回答1:

One way to do it is using an array to keep record what been selected/deselected, and rebuild your options everytime user click.

js:

var record = [];

var selectAllItems = function (target) {
    //toggle all options here and keep a record in "record" array ...
}

var doTheMagic = function(target){
    record[target.selectedIndex] = ! record[target.selectedIndex];
    rebuildOptions();

}

var rebuildOptions = function (){
    var itemsList = document.getElementById('itemsList');
    for (var i=0;i<record.length;i++){
            itemsList.options[i].selected = record[i];
    }

}

html:

<select id="itemsList" multiple="true" size="3"  onclick="doTheMagic(this)">
    <option value="volvo">Volvo</option>
    <option value="saab">Saab</option>
    <option value="audi">Audi</option>
</select>
<input type="checkbox" id="bSelectAll" onclick="selectAllItems(this)" />Select all

jsFiddle demo: http://jsfiddle.net/3A9Xs/3/



回答2:

This snippet uses onclick, and should work for older IEs too.

In IEs selectedIndex always returns the first found selected index of the select instead of user selected index. A fix is to cache the current value of the select, which at the beginning of the function is the actually selected value. IE changes that value during the iteration, that's why caching is needed.

var select = document.getElementById('select'),
    toggle = document.getElementById('toggle'),
    options = select.options,
    selections = [],
    selectOption = function (e) {
        var n,
            target = e.target || e.srcElement,
            currentValue = target.value;
        for (n = 0; n < options.length; n++) {
            if (currentValue === options[n].value) { // or options[n].text, if values are not defined
                selections[n] = !selections[n];
            }
            options[n].selected = selections[n];
        }
    },
    toggleAll = function () {
        var n, bool = this.checked;
        for (n = 0; n < options.length; n++) {
            options[n].selected = bool;
            selections[n] = bool;
        }
    },
    n;
for (n = 0; n < options.length; n++) {
    selections.push(options[n].selected);
}
if (select.addEventListener) {
    select.addEventListener('click', selectOption);
    toggle.addEventListener('click', toggleAll);
} else {
    select.attachEvent('onclick', selectOption);
    toggle.attachEvent('onclick', toggleAll);
}

A live demo at jsFiddle.