javascript 如何使 HTML 多选行为就像始终按住控制按钮一样
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12585863/
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
How can I make an HTML multiple select act like the control button is held down always
提问by Matt F.
I have a web application I'm working on that requires a HTML multiple select element operates like the control key is held down at all times. I.e. click on an option will toggle whether it is selected or not.
我有一个我正在处理的 Web 应用程序,它需要一个 HTML 多选元素,就像始终按住控制键一样。即单击一个选项将切换它是否被选中。
I have tried various Jquery event binds but it appears that the standard HTML multiple select behavior executes before the Jquery bound event fires, making it all but impossible to simply intercept the event and modify the standard behavior.
我尝试了各种 Jquery 事件绑定,但似乎标准 HTML 多选行为在 Jquery 绑定事件触发之前执行,这使得简单地拦截事件并修改标准行为几乎是不可能的。
How can I make is so that single clicks will toggle the selection of an individual option?
我怎样才能使单击将切换单个选项的选择?
回答by iambriansreed
Try this out. You can store the option values in an object and use the click action to update the object then apply the changes to the select.
试试这个。您可以将选项值存储在对象中并使用单击操作更新对象,然后将更改应用于选择。
Demo
演示
http://jsfiddle.net/iambriansreed/BSdxE/
http://jsfiddle.net/iambriansreed/BSdxE/
HTML
HTML
<select class="select-toggle" multiple="multiple">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>?
JavaScript
JavaScript
$('.select-toggle').each(function(){
var select = $(this), values = {};
$('option',select).each(function(i, option){
values[option.value] = option.selected;
}).click(function(event){
values[this.value] = !values[this.value];
$('option',select).each(function(i, option){
option.selected = values[option.value];
});
});
});?
回答by Hazem Salama
You may want to consider a simpler solution, like using a list of checkboxes inside a div whose overflow property is set to scroll. That might work out better for you. Getting a drop down to do what you've asked is a bit involved.
您可能需要考虑一个更简单的解决方案,例如在溢出属性设置为滚动的 div 中使用复选框列表。那可能对你更有效。让下拉菜单执行您所要求的操作有点复杂。
See this fiddlefor example
例如,请参阅此小提琴
HTML
HTML
<div id="container">
<label><input type="checkbox" name="test" value="1" />Option 1</label>
<label><input type="checkbox" name="test" value="2" />Option 2</label>
<label><input type="checkbox" name="test" value="3" />Option 3</label>
<label><input type="checkbox" name="test" value="4" />Option 4</label>
<label><input type="checkbox" name="test" value="5" />Option 5</label>
<label><input type="checkbox" name="test" value="6" />Option 6</label>
<label><input type="checkbox" name="test" value="7" />Option 7</label>
<label><input type="checkbox" name="test" value="8" />Option 8</label>
<label><input type="checkbox" name="test" value="9" />Option 9</label>
<label><input type="checkbox" name="test" value="10" />Option 10</label>
<label><input type="checkbox" name="test" value="11" />Option 11</label>
<label><input type="checkbox" name="test" value="12" />Option 12</label>
</div>
CSS
CSS
label{display:block;}
#container{height:100px;width:200px;overflow:scroll;}
回答by Sergio
Had to solve this problem myself and noticed the bugged behavior a simple interception of the mousedown
and 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 Joeytje50
The above solutions all have the major downside of not supporting selections in the checkbox, which is actually the reason I'd use <select>
-boxes over checkbox-inputs in the first place. Initially I visited this page to find a built-in way to fix this, but considering the above answers, I'll just write my own code.
上述解决方案都有不支持复选框中的选择的主要缺点,这实际上是我首先使用<select>
-boxes 而不是 checkbox-inputs的原因。最初我访问此页面以找到解决此问题的内置方法,但考虑到上述答案,我将只编写自己的代码。
The following code also has the advantage that it doesn't update on mouseup as opposed to the current top answer by iambriansreed, but on mousedown, which is the default behaviour in browsers.
以下代码的另一个优点是它不会在 mouseup 上更新,而不是在 iambriansreed 的当前最佳答案上更新,而是在 mousedown 上更新,这是浏览器中的默认行为。
Just to help out future googlers, my code below:
只是为了帮助未来的谷歌员工,我的代码如下:
// Copyright (c) 2018 Joeytje50. All rights reserved.
// This code is licenced under GNU GPL3+; see <http://www.gnu.org/licenses/>
// Source code and most recent version:
// https://gist.github.com/Joeytje50/2b73f9ac47010e7fdc5589788b80af77
// select all <options> within `sel` in the range [from,to]
// change their state to the state sel.options[from] is in,
// ie. change it to the current state of the first selected element
function selectRange(sel, from, to) {
var toState = sel.options[from].selected;
// make sure from < to:
if (from > to) {
var temp = from;
from = to;
to = temp;
}
if (!(sel instanceof HTMLSelectElement)) {
throw new TypeError('selectRange requires a single non-jQuery select-element as first parameter');
}
// (de)select every element
for (var i=from; i<=to; i++) {
sel.options[i].selected = toState;
}
}
$(function() {
$('.addSelect').data('select-start', 0); // default selection start
$('.addSelect').on('mousedown', function(e) {
$(this).focus();
// clicking on the edge of the <select> shouldn't do anything special
if (!$(e.target).is('option')) return;
// if Ctrl is pressed, just let the built-in functionality take over
if (e.ctrlKey) return;
// keep everything selected that's not affected by the range within a shift-click
if (e.shiftKey) {
var fromIdx = $(this).data('select-start')
selectRange(this, $(this).data('select-start'), e.target.index);
e.preventDefault();
return false;
}
// save the starting <option> and the state to change to
$(this).data('select-start', e.target.index);
e.target.selected = !e.target.selected;
e.preventDefault();
// save a list of selected elements, to make sure only the selected <options>
// are added or removed when dragging
var selected = [];
for (var i=0;i<this.selectedOptions.length;i++) {
selected.push(this.selectedOptions[i].index);
}
$(this).data('selected', selected);
$(this).children('option').on('mouseenter', function(e) {
var sel = this.parentElement;
// first reset all options to the original state
for (var i=0;i<sel.options.length;i++) {
if ($(sel).data('selected').indexOf(i) == -1) {
sel.options[i].selected = false;
} else {
sel.options[i].selected = true;
}
}
// then apply the new range to the elements
selectRange(sel, $(sel).data('select-start'), e.target.index);
});
});
// clean up events after click event has ended.
$(window).on('mouseup', function() {
$('.addSelect').children('option').off('mouseenter'); // remove mouseenter-events
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="addSelect" multiple size="10">
<option value="0">Foo0</option>
<option value="1">Bar1</option>
<option value="2">Baz2</option>
<option value="3">Lol3</option>
<option value="4">Heh4</option>
<option value="5">Hey5</option>
<option value="6">Meh6</option>
<option value="7">Xcq7</option>
<option value="8">Hmm8</option>
<option value="9">End9</option>
</select>
Feel free to use this code by simply copying it to any project you'd like to use it on.
随意使用此代码,只需将其复制到您想在其上使用的任何项目即可。