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

IT技术 javascript html forms dom
2021-01-18 06:47:04

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

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

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

5个回答

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

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

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

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

很好的解决方案。我注意到的唯一缺点是事件预防的工作方式是父选择不关注的,导致不同的外观和感觉(灰色而不是所选选项的蓝色背景)。为了保持外观和感觉,我手动专注于选择框。$(this.parentElement).focus();
2021-03-22 06:47:04
你可以! this.selected在那里使用
2021-03-23 06:47:04
正如其他人所说,为了简化它只是this.selected = !this.selected;真的没有必要使用 jQuery
2021-03-25 06:47:04
这取决于 jQuery。请确保在加载 DOM 元素并准备好绑定到事件后执行上述代码。一个放置它的好地方将是你的$(document).ready(...)
2021-03-28 06:47:04
不能正常工作。拖动鼠标后,它会取消选择所有选项。
2021-04-09 06:47:04

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

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

注意:此代码通过替换 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>

这对我有用,但选择不会使表单变脏 ( e.preventDefault())。只是要记住一些东西。
2021-03-29 06:47:04
请解释您所说的“错误行为”是什么意思
2021-03-29 06:47:04
有什么作用e.preventDefault()
2021-04-12 06:47:04

techfoobar的答案是错误的,如果您拖动鼠标,它会取消选择所有选项。

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

试试这个答案

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

编辑 (2020)

在我最初的回答之后 5 年,我认为这里的最佳做法是用复选框替换下拉列表。想想看,这就是复选框首先存在的主要原因,它可以很好地与旧浏览器(如 IE 和现代手机)配合使用,无需任何自定义 JS 来处理所有古怪的场景。

这确实是最好的,单击时不会向上滚动。
2021-03-17 06:47:04

死灵法术。
没有 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
    );
});
它仍然跳到第一个选项我做错了什么?
2021-03-30 06:47:04

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

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

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;
});

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