javascript 在不使用 ctrl 键的情况下从 html select 元素中选择多个
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24543862/
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
Selecting multiple from an html select element without using ctrl key
提问by Zatos
I've come across various solutions to this issue on the net.
我在网上遇到过针对这个问题的各种解决方案。
Basically, I find having to hold down ctrl a bit cheesy, and I want the select list to just select whatever I click on and add it to the currently selected items.
基本上,我发现必须按住 ctrl 有点俗气,我希望选择列表只选择我单击的任何内容并将其添加到当前选定的项目中。
I've already got this code:
我已经有了这个代码:
$("select[multiple] option").mousedown(function () {
var $self = $(this);
if ($self.attr("selected")) {
$self.removeAttr("selected", "");
}
else {
$self.attr("selected", "selected");
}
return false;
});
Element:
元素:
<select multiple id="WOStatusKey" name="WOStatusKey">
<option value="1">Created</option>
<option value="2">In Process</option>
<!-- etc. (about 20 of these) -->
</select>
It works fine with one exception: any time something is selected/deselected that is not at the top of the list (where you have to scroll to see it) then it pops back up to the top after you select it. I've played around with it a little bit but can't figure out anything to prevent this behavior. Also, I've seen a couple other solutions to this problem, although nothing that either works or works well.
它工作正常,但有一个例外:任何时候选择/取消选择不在列表顶部(您必须滚动才能看到它)的内容,然后在您选择它后它会弹回到顶部。我已经玩了一点,但无法想出任何办法来防止这种行为。此外,我已经看到了解决这个问题的其他几个解决方案,尽管没有任何方法可以正常工作或运行良好。
I only need this to work in Chrome. Also, I am not interested in any alternative solutions to using a select list.
我只需要它在 Chrome 中工作。此外,我对使用选择列表的任何替代解决方案都不感兴趣。
Thank you for any help, it is much appreciated.
感谢您的任何帮助,非常感谢。
回答by Tony Brix
You can save the Element.scrollTopand set it at the end.
您可以保存Element.scrollTop并将其设置在最后。
$("select").mousedown(function(e){
e.preventDefault();
var select = this;
var scroll = select .scrollTop;
e.target.selected = !e.target.selected;
setTimeout(function(){select.scrollTop = scroll;}, 0);
$(select ).focus();
}).mousemove(function(e){e.preventDefault()});
回答by Luke
Here is a pure JS solution:
这是一个纯JS解决方案:
element.onmousedown= function(event) {
//this == event.target
event.preventDefault();
var scroll_offset= this.parentElement.scrollTop;
this.selected= !this.selected;
this.parentElement.scrollTop= scroll_offset;
}
element.onmousemove= function(event) {
event.preventDefault();
}
Look at the parent element(the select box) and record the vertical scroll offset before selecting/deselecting the option. Then reset it manually once you have performed the action.
在选择/取消选择选项之前,查看父元素(选择框)并记录垂直滚动偏移。然后在您执行操作后手动重置它。
The reasoning behind preventing default behavior for the mousemove
event is because if you don't prevent it and you happen to click an option while moving the mouse, all options will become de-selected.
阻止该mousemove
事件的默认行为背后的原因是因为如果您不阻止它并且您在移动鼠标时碰巧单击了一个选项,则所有选项都将被取消选择。
回答by Cassio Ludewigs
Tony's answer makes the select arrows buggy, as they work only if you hold the mouse down.
托尼的回答使选择箭头有问题,因为它们只有在您按住鼠标时才起作用。
I've combined a few solutions into this, and it works fine at least in Chrome and FF:
我已经结合了一些解决方案,它至少在 Chrome 和 FF 中运行良好:
// multiple select: selectable without Control
$('select[multiple] option').on('mousedown', function(e) {
var $this = $(this),
that = this,
scroll = that.parentElement.scrollTop;
e.preventDefault();
$this.prop('selected', !$this.prop('selected'));
setTimeout(function() {
that.parentElement.scrollTop = scroll;
}, 0);
return false;
});
回答by Tim Yonker
Here's a solution that appears to work in Chrome FF and IE. It's not terribly pretty because it flashes a little bit when clicking.
这是一个似乎适用于 Chrome FF 和 IE 的解决方案。它不是非常漂亮,因为单击时它会闪烁一点。
var vals = [];
$("select[multiple]").click(function(e){
var scroll_offset= this.scrollTop;
var newVals = $(this).val();
if (newVals.length === 1) {
var index = vals.indexOf(newVals[0])
if (index > -1) {
vals.splice(index, 1);
} else {
vals.push(newVals[0])
}
$(this).val(vals);
this.scrollTop = scroll_offset;
}
});
回答by Steve
For a pure js solution in chrome set the event listener on "onmouseup" instead. The event that resets the scroll to the first element is fired on the mouse up. So for example:
对于 chrome 中的纯 js 解决方案,请将事件侦听器设置为“onmouseup”。将滚动重置为第一个元素的事件在鼠标向上时触发。例如:
element.onmouseup = function(event) {
event.preventDefault();
var st = this.scrollTop;
setTimeout(function () { element.scrollTop = st; }, 0);
};
回答by ZPiDER
This worked better for me than the other suggestions, because it is vanilla JS and it behaves more similarly to the original still, for example allows quick selection of many items via the shift key.
这对我来说比其他建议更有效,因为它是 vanilla JS 并且它的行为与原始静止更相似,例如允许通过 shift 键快速选择许多项目。
element.onmousedown = function(event) {
if (event.shiftKey) return;
event.preventDefault();
this.focus();
var scroll = this.scrollTop;
event.target.selected = !event.target.selected;
this.scrollTop = scroll;
// make sure that other listeners (like Vue) pick up on the change
// even though we prevented the default.
this.dispatchEvent(new Event("change"));
}