如何避免使用 Javascript 在多选框中按 ctrl-click 的需要?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8641729/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 06:52:17  来源:igfitidea点击:

How to avoid the need for ctrl-click in a multi-select box using Javascript?

javascripthtmlformsdom

提问by bokov

I thought this would be a simple hack, but I've now been searching for hours and can't seen to find the right search term. I want to have an ordinary multiple select box (<select multiple="multiple">) except I don't want the user to have to hold down the control key to make multiple selections.

我认为这将是一个简单的黑客攻击,但我现在已经搜索了几个小时,但找不到正确的搜索词。我想要一个普通的多选框 ( <select multiple="multiple">),除非我不希望用户必须按住控制键才能进行多选。

In other words, I want a left click to toggle the <option>element that's under the cursor without changing any of the others. In other other words, I want something that looks like a combo list box but behaves like a group of check boxes.

换句话说,我希望左键单击来切换<option>光标下的元素,而不更改任何其他元素。换句话说,我想要一些看起来像组合列表框但行为像一组复选框的东西。

Can anybody suggest a simple way to do this in Javascript? Thanks.

任何人都可以建议一种在 Javascript 中执行此操作的简单方法吗?谢谢。

回答by techfoobar

Check this fiddle: http://jsfiddle.net/xQqbR/1022/

检查这个小提琴:http: //jsfiddle.net/xQqbR/1022/

You basically need to override the mousedownevent for each <option>and toggle the selectedproperty there.

您基本上需要覆盖mousedown每个事件<option>并在selected那里切换属性。

$('option').mousedown(function(e) {
    e.preventDefault();
    $(this).prop('selected', !$(this).prop('selected'));
    return false;
});

For simplicity, I've given 'option' as the selector above. You can fine tune it to match <option>sunder specific <select>element(s). For ex: $('#mymultiselect option')

为简单起见,我将 'option' 作为上面的选择器。您可以微调它以匹配<option>s特定<select>元素。例如:$('#mymultiselect option')

回答by Sergio

Had to solve this problem myself and noticed the bugged behavior a simple interception of the mousedownand setting the attribute would have, so made a override of the select element and it works good.

必须自己解决这个问题,并注意到简单的拦截mousedown和设置属性会产生的错误行为,因此覆盖了 select 元素并且效果很好。

jsFiddle: http://jsfiddle.net/51p7ocLw/

jsFiddle:http: //jsfiddle.net/51p7ocLw/

Note:This code does fix buggy behavior by replacing the select element in the DOM. This is a bit agressive and will break event handlers you might have attached to the element.

注意:此代码通过替换 DOM 中的 select 元素确实修复了错误行为。这有点激进,会破坏您可能附加到元素的事件处理程序。

window.onmousedown = function (e) {
    var el = e.target;
    if (el.tagName.toLowerCase() == 'option' && el.parentNode.hasAttribute('multiple')) {
        e.preventDefault();

        // toggle selection
        if (el.hasAttribute('selected')) el.removeAttribute('selected');
        else el.setAttribute('selected', '');

        // hack to correct buggy behavior
        var select = el.parentNode.cloneNode(true);
        el.parentNode.parentNode.replaceChild(select, el.parentNode);
    }
}
<h4>From</h4>

<div>
    <select name="sites-list" size="7" multiple>
        <option value="site-1">SITE</option>
        <option value="site-2" selected>SITE</option>
        <option value="site-3">SITE</option>
        <option value="site-4">SITE</option>
        <option value="site-5">SITE</option>
        <option value="site-6" selected>SITE</option>
        <option value="site-7">SITE</option>
        <option value="site-8">SITE</option>
        <option value="site-9">SITE</option>
    </select>
</div>

回答by evilReiko

techfoobar's answer is buggy, it unselects all options if you drag the mouse.

techfoobar 的回答有问题,如果您拖动鼠标,它会取消选择所有选项。

Sergio's answer is interesting, but cloning and removing events-bound to a dropdown is not a nice thing.

Sergio 的回答很有趣,但是克隆和删除绑定到下拉列表的事件并不是一件好事。

Try this answer.

试试这个答案

Note: Doesn't work on Firefox, but works perfectly on Safari/Chrome/Opera. (I didn't test it on IE)

注意:在 Firefox 上不起作用,但在 Safari/Chrome/Opera 上完美运行。(我没有在 IE 上测试过)

回答by Stefan Steiger

Necromancing.
The selected answer without jQuery.
Also, it missed setting the focus when an option is clicked, because you have to do this yourself, if you write e.preventDefault...
Forgetting to do focus would affect CSS-styling, e.g. bootstrap, etc.

死灵法术。
没有 jQuery 的选定答案。
此外,当一个选项被点击时,它错过了设置焦点,因为你必须自己做这件事,如果你写 e.preventDefault...
忘记做焦点会影响 CSS 样式,例如引导程序等。

var options = [].slice.call(document.querySelectorAll("option"));

options.forEach(function (element)
{
    // console.log("element", element);
    element.addEventListener("mousedown", 
        function (e)
        {
            e.preventDefault();
            element.parentElement.focus();
            this.selected = !this.selected;
            return false;
        }
        , false
    );
});

回答by Marino Di Clemente

I had same problem today, generally the advice is to use a list of hidden checkboxes and emulate the behavior via css, in this way is more easy to manage but in my case i don't want to modify html.

我今天遇到了同样的问题,一般建议是使用隐藏复选框列表并通过 css 模拟行为,这样更容易管理,但在我的情况下,我不想修改 html。

At the moment i've tested this code only with google chrome, i don't know if works with other browser but it should:

目前我只用谷歌浏览器测试了这段代码,我不知道是否适用于其他浏览器,但它应该:

var changed;
$('select[multiple="multiple"]').change(function(e) {
    var select = $(this);
    var list = select.data('prevstate');
    var val = select.val();
    if (list == null) {
        list = val;
    } else if (val.length == 1) {
        val = val.pop();
        var pos = list.indexOf(val);
        if (pos == -1)
            list.push(val);
        else
            list.splice(pos, 1);
    } else {
        list = val;
    }
    select.val(list);
    select.data('prevstate', list);
    changed = true;
}).find('option').click(function() {
    if (!changed){
        $(this).parent().change();
    }
    changed = false;
});

Of course suggestions are welcome but I have not found another way

当然欢迎提出建议,但我还没有找到其他方法