如何避免使用 Javascript 在多选框中进行 ctrl-click 的需要?
Posted
技术标签:
【中文标题】如何避免使用 Javascript 在多选框中进行 ctrl-click 的需要?【英文标题】:How to avoid the need for ctrl-click in a multi-select box using Javascript? 【发布时间】:2012-01-28 07:53:46 【问题描述】:我认为这将是一个简单的 hack,但我现在已经搜索了几个小时,但无法找到正确的搜索词。我想要一个普通的多选框(<select multiple="multiple">
),但我不希望用户必须按住控制键才能进行多选。
换句话说,我希望左键单击以切换光标下的<option>
元素,而不更改任何其他元素。换句话说,我想要一个看起来像组合列表框但行为像一组复选框的东西。
任何人都可以提出一个简单的方法来用 javascript 做到这一点吗?谢谢。
【问题讨论】:
如果你不介意改变你的标记,你可以建立一个复选框和标签列表,然后隐藏复选框,并设置标签的样式(当它被选中时)具有相似的视觉外观到<select multiple>
。 Demo in fiddle
【参考方案1】:
检查这个小提琴:http://jsfiddle.net/xQqbR/1022/
您基本上需要为每个<option>
覆盖mousedown
事件并在那里切换selected
属性。
$('option').mousedown(function(e)
e.preventDefault();
$(this).prop('selected', !$(this).prop('selected'));
return false;
);
为简单起见,我在上面给出了“选项”作为选择器。您可以对其进行微调以匹配特定 <select>
元素下的 <option>s
。例如:$('#mymultiselect option')
【讨论】:
你可以在那里使用! this.selected
。
这依赖于 jQuery。请确保在加载 DOM 元素并准备好绑定到事件后执行上述代码。放置它的好地方是您的$(document).ready(...)
无法正常工作。一旦你拖动鼠标,它就会取消选择所有选项。
非常好的解决方案。我注意到的唯一缺点是事件预防以父选择不关注的方式工作,从而导致不同的外观和感觉(灰色而不是所选选项的蓝色背景)。为了保持外观和感觉,我手动专注于选择框。 $(this.parentElement).focus();
正如其他人所说,为了简化它只是this.selected = !this.selected;
真的没有必要使用jQuery【参考方案2】:
必须自己解决这个问题,并注意到bugged behavior a simple interception of the mousedown
和设置属性会有,所以覆盖了 select 元素并且效果很好。
jsFiddle: http://jsfiddle.net/51p7ocLw/
注意:此代码确实通过替换 DOM 中的选择元素来修复错误行为。这有点激进,并且会破坏您可能附加到元素的事件处理程序。
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()
)。只是要记住的事情。
请解释您所说的“错误行为”是什么意思
e.preventDefault()
是做什么的?【参考方案3】:
techfoobar的回答有问题,如果你拖动鼠标,它会取消选择所有选项。
Sergio 的回答很有趣,但是克隆和删除绑定到下拉列表的事件并不是一件好事。
Try this answer.
注意:不适用于 Firefox,但可以在 Safari/Chrome/Opera 上完美运行。 (我没在IE上测试过)
编辑(2020 年)
在我最初回答 5 年后,我认为这里的最佳做法是用复选框替换下拉菜单。想想看,这就是复选框首先存在的主要原因,它可以很好地与 IE 和现代手机等旧浏览器配合使用,无需任何自定义 JS 来处理所有古怪的场景。
【讨论】:
这个确实是最好的,点击时不会向上滚动。【参考方案4】:死灵术。 没有 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
);
);
【讨论】:
它仍然跳到第一个选项我做错了什么?【参考方案5】:我今天遇到了同样的问题,一般建议是使用隐藏复选框列表并通过 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;
);
当然欢迎提出建议,但我还没有找到其他方法
【讨论】:
以上是关于如何避免使用 Javascript 在多选框中进行 ctrl-click 的需要?的主要内容,如果未能解决你的问题,请参考以下文章