Javascript 单击时如何选中/取消选中单选按钮?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4957207/
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 to check/uncheck radio button on click?
提问by Richard Knop
I want to be able to uncheck a radio button by clicking on it.
我希望能够通过单击来取消选中一个单选按钮。
So, if a radio button is unchecked, I want to check it, if it is checked, I want to uncheck it.
所以,如果一个单选按钮没有被选中,我想选中它,如果它被选中,我想取消选中它。
This does not work:
这不起作用:
$('input[type=radio]:checked').click(function(){
$(this).attr('checked', false);
});
I am not able to check a radio button now.
我现在无法检查单选按钮。
回答by HexInteractive
This is notto replace a checkbox, it's to allow a radio group to go back to an unselected state. This was tricky because the radio selection doesn't act like a normal event.
这不是要替换复选框,而是要允许无线电组返回到未选中状态。这很棘手,因为无线电选择不像正常事件。
The browser handles radio buttons outside the normal event chain. So, a click handler on a radiobutton with event.preventDefault() or event.stopPropagation() will NOT prevent the radiobutton from being checked. The .removeAttr('checked') must be done in a setTimeout to allow the event to finish, and the browser to check the radiobutton (again), and then the setTimeout will fire.
浏览器处理普通事件链之外的单选按钮。因此,带有 event.preventDefault() 或 event.stopPropagation() 的单选按钮上的单击处理程序不会阻止单选按钮被检查。.removeAttr('checked') 必须在 setTimeout 中完成以允许事件完成,并且浏览器检查单选按钮(再次),然后 setTimeout 将触发。
This also correctly handles the case where a user starts the mousedown but leaves the radiobutton before mouseup.
这也可以正确处理用户启动鼠标按下但在鼠标按下之前离开单选按钮的情况。
//$ = jQuery;
$(':radio').mousedown(function(e){
var $self = $(this);
if( $self.is(':checked') ){
var uncheck = function(){
setTimeout(function(){$self.removeAttr('checked');},0);
};
var unbind = function(){
$self.unbind('mouseup',up);
};
var up = function(){
uncheck();
unbind();
};
$self.bind('mouseup',up);
$self.one('mouseout', unbind);
}
});
I hope this helps
我希望这有帮助
回答by Stephen
try this:
尝试这个:
$('input[type=radio]').click(function(){
if (this.previous) {
this.checked = false;
}
this.previous = this.checked;
});
回答by Jase in ATL
The accepted answer does not work on mobile devices. It relies on setTimeout and bindings that are related to mouse events that just don't fire on tablets/mobile devices.
My solution is to manually track the selected state using the "click" event handler and a custom class state.
接受的答案不适用于移动设备。它依赖于 setTimeout 和与鼠标事件相关的绑定,这些鼠标事件不会在平板电脑/移动设备上触发。
我的解决方案是使用“单击”事件处理程序和自定义类状态手动跟踪所选状态。
- handle the click events on the radio input elements
- check if the "selected" class exists on the clicked element
- if it does, (meaning it has been clicked before), remove the class and uncheck the element, return
- if it doesn't, remove the class from all elements of the same name and add it to only the clicked element.
- 处理单选输入元素上的点击事件
- 检查单击的元素上是否存在“选定”类
- 如果是,(意味着它之前被点击过),删除类并取消选中元素,返回
- 如果不是,则从所有同名元素中删除该类并将其添加到仅单击的元素中。
No need to prevent default behaviors. Here is the code in Jquery:
无需阻止默认行为。这是Jquery中的代码:
$("input:radio").on("click",function (e) {
var inp=$(this); //cache the selector
if (inp.is(".theone")) { //see if it has the selected class
inp.prop("checked",false).removeClass("theone");
return;
}
$("input:radio[name='"+inp.prop("name")+"'].theone").removeClass("theone");
inp.addClass("theone");
});
回答by James Barnsley
This is the real solution ...
这是真正的解决方案......
var check;
$('input[type="radio"]').hover(function() {
check = $(this).is(':checked');
});
$('input[type="radio"]').click(function() {
check = !check;
$(this).attr("checked", check);
});
Try it, it works for me!
试试吧,它对我有用!
回答by Daric
If there is only one radio button you needs to use checkbox instead.
如果只有一个单选按钮,则需要改用复选框。
There is no meaning to having one radio button they works with group.
有一个单选按钮与组一起工作是没有意义的。
probably you are looking for checkbox control.
可能您正在寻找复选框控件。
回答by Eterm
It is better UX to have a default-selected "Select none" explicit option, and not let the user uncheck any radio button.
最好有一个默认选择的“不选择”显式选项,而不是让用户取消选中任何单选按钮。
(List item 9 in this nngroup (neilsen) article:
(在这篇 nngroup (neilsen) 文章中列出第 9 项:
http://www.nngroup.com/articles/checkboxes-vs-radio-buttons/
http://www.nngroup.com/articles/checkboxes-vs-radio-buttons/
回答by ArkTekniK
I know this question is old, but I just came across this problem and decided to have a go myself and didn't want to use a modifier button like ctrl.
我知道这个问题很老,但我刚刚遇到了这个问题,并决定自己尝试一下,不想使用像 ctrl 这样的修饰按钮。
See fiddle at http://jsfiddle.net/ArktekniK/yhbw469f/For toggling a radio button by clicking on the radio button itself
请参阅http://jsfiddle.net/ArktekniK/yhbw469f/ 上的小提琴 通过单击单选按钮本身来切换单选按钮
$('input[type=radio]').on('mousedown', function(e){
var wasChecked = $(this).prop('checked');
this.turnOff = wasChecked;
$(this).prop('checked', !wasChecked);
});
$('input[type=radio]').on('click', function(e){
$(this).prop('checked', !this.turnOff);
this['turning-off'] = !this.turnOff;
});
For toggling a radio button by clicking on the label or radio button itself
用于通过单击标签或单选按钮本身来切换单选按钮
$('label:has(input[type=radio])').on('mousedown', function(e){
var radio = $(this).find('input[type=radio]');
var wasChecked = radio.prop('checked');
radio[0].turnOff = wasChecked;
radio.prop('checked', !wasChecked);
});
$('label:has(input[type=radio])').on('click', function(e){
var radio = $(this).find('input[type=radio]');
radio.prop('checked', !radio[0].turnOff);
radio[0]['turning-off'] = !radio[0].turnOff;
});
回答by gman
I must be missing it but after all these years AFAIK none of the solutions above seem to work or maybe I'm just dumb.
我一定很想念它,但经过这么多年,AFAIK 上面的解决方案似乎都不起作用,或者我可能只是愚蠢。
There is absolutely no reason to use a radio button unless there is more than one radio button in the same group. If it's a lone radio button then just use a checkbox. The reason to use a radio button is for selecting one of mutually exclusive options. That means any solution which only looks at individual buttons will fail since clicking a one button will effect the state of the other buttons
除非在同一组中有多个单选按钮,否则绝对没有理由使用单选按钮。如果它是一个单独的单选按钮,那么只需使用一个复选框。使用单选按钮的原因是为了选择互斥选项之一。这意味着任何只查看单个按钮的解决方案都将失败,因为单击一个按钮会影响其他按钮的状态
In other words since we're using radioboxes the solution needs to work for
换句话说,由于我们使用的是radioboxes,因此解决方案需要为
<input type="radio" name="foo" id="foo1"><label for="foo1">foo1</label>
<input type="radio" name="foo" id="foo2"><label for="foo2">foo2</label>
<input type="radio" name="foo" id="foo3"><label for="foo3">foo3</label>
Here's one that looks at all the buttons.
这是查看所有按钮的一个。
This seems to work
这似乎有效
document.querySelectorAll(
'input[type=radio][name=foo]').forEach((elem) => {
elem.addEventListener('click', allowUncheck);
// only needed if elem can be pre-checked
elem.previous = elem.checked;
});
function allowUncheck(e) {
if (this.previous) {
this.checked = false;
}
// need to update previous on all elements of this group
// (either that or store the id of the checked element)
document.querySelectorAll(
`input[type=radio][name=${this.name}]`).forEach((elem) => {
elem.previous = elem.checked;
});
}
body { font-size: xx-large; }
label, input {
/* added because a second click to unselect radio often
appears as a double click to select text */
-webkit-user-select: none;
user-select: none;
}
<input type="radio" name="foo" id="foo1"><label for="foo1">foo1</label>
<input type="radio" name="foo" id="foo2"><label for="foo2">foo2</label>
<input type="radio" name="foo" id="foo3"><label for="foo3">foo3</label>
note if elem.previous
worries you you could use elem.dataset.previous
请注意是否elem.previous
担心您可以使用elem.dataset.previous
Another solution would be to store which button is checked
另一种解决方案是存储选中的按钮
function makeRadioboxGroupUnCheckable(groupSelector) {
let currentId;
document.querySelectorAll(groupSelector).forEach((elem) => {
elem.addEventListener('click', allowUncheck);
// only needed if can be pre-checked
if (elem.checked) {
currentId = elem.id;
}
});
function allowUncheck(e) {
if (this.id === currentId) {
this.checked = false;
currentId = undefined;
} else {
currentId = this.id;
}
}
}
makeRadioboxGroupUnCheckable('input[type=radio][name=foo]');
body { font-size: xx-large; }
label, input {
/* added because a second click to unselect radio often
appears as a double click to select text */
-webkit-user-select: none;
user-select: none;
}
<input type="radio" name="foo" id="foo1"><label for="foo1">foo1</label>
<input type="radio" name="foo" id="foo2"><label for="foo2">foo2</label>
<input type="radio" name="foo" id="foo3"><label for="foo3">foo3</label>
回答by Eugeny K
Who those who are seeking for a pure JavaScript solution I modified the code from Jase in ATL's answer.
谁正在寻求纯 JavaScript 解决方案,我修改了ATL答案中Jase的代码。
I wrote this code for proposal of use with a CSS styled 3 position switch which provides 4 state of toggling (On, Off, Neutral and Unactivated).
我编写此代码是为了建议与 CSS 样式的 3 位置开关一起使用,该开关提供 4 种切换状态(开、关、中性和未激活)。
function toggle_radio(ev) {
var radio = ev.target;
var cut_pos = radio.className.indexOf(' switcher-active');
// the switch itself
if (cut_pos !== -1) { // if the button checked it is '.switcher-active'
radio.checked = false; // toggle its state
radio.className = radio.className.slice(0, cut_pos); // remove '.switcher-active'
return true; // work is done. Break the function
}
// the button was inactive before it was clicked. Then it should became '.switcher-active'
radio.className = radio.className + ' switcher-active';
// we need to remove '.switcher-active' if either the left or right radio button was clicked. This part is uggly but I don't bother, because I'm late for barber
var radios = document.getElementsByName(radio.name); // get all these radio siblings as a collection of elements
for (var i=0; i < radios.length; i++) { // iterate through the collection
if (radios[i].className.indexOf('switcher-radio-neutral') !== -1)
continue; // skip the '.switcher-neutral' radio input
radios[i].onclick = function(ev2) {
sib_radios = document.getElementsByName(ev2.target.name); // get a group of radio inputs linked by the name
// get the '.switcher-neutral'
for (var k=0, cut_pos = -1, sib; k < sib_radios.length; k++) {
sib = sib_radios[k];
cut_pos = sib.className.indexOf(' switcher-active');
if (cut_pos !== -1)
sib.className = sib.className.slice(0, cut_pos);
}
}
}
}
var switchers = document.getElementsByClassName('switcher-radio-neutral');
for (var i=0; i < switchers.length; i++) { // bind onclick handlers
switchers[i].onclick = toggle_radio;
}
.switcher {
position: relative;
display: inline-block;
margin: 1px 10px;
height: 20px;
width: 58px;
z-index: 1;
}
.switcher-off {
left: 1px;
width: 33%;
height: 100%;
}
.switcher-neutral {
left: 33%;
width: 33%;
height: 100%;
}
.switcher-on{
right: 1px;
width: 33%;
height: 100%;
}
.switcher-label {
position: absolute;
text-indent: -9999px;
z-index: 2;
}
.switcher input {
visibility: hidden;
position: absolute;
}
.switcher-slider {
height: 100%;
width: 100%;
border-radius: 10px;
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.1) inset, 0 0 4px rgba(0, 0, 0, 0.5) inset, 0 2px 2px 1px rgba(0, 0, 0, 0.3) inset;
transition: background-color 0.2s linear 0s;
}
.switcher-slider:after {
transition: left 0.2s linear 0s, right 0.2s linear 0s;
background: linear-gradient(#D0D0D0, #FDFDFD) repeat scroll 0 0 rgba(0, 0, 0, 0);
content: "";
position: absolute;
top: 1px;
border-radius: 50%;
height: calc(100% - 2px);
width: calc(100%/3 - 1px);
box-shadow: 0 0 1px 1px #f4f4f4 inset, 0 0 3px 1px rgba(0, 0, 0, 0.6);
left: 33%;
}
.switcher-radio-on:checked ~ .switcher-slider {
background-color: #81EA89;
}
.switcher-radio-neutral:checked ~ .switcher-slider {
background: #ddd;
}
.switcher-radio-off:checked ~ .switcher-slider {
background-color: #ED8282;
}
.switcher-radio-on:checked ~ .switcher-slider:after {
left: calc(2*(100%/3));
}
.switcher-radio-neutral:checked ~ .switcher-slider:after {
left: calc(1px + 100%/3);
}
.switcher-radio-off:checked ~ .switcher-slider:after {
left: 1px;
}
<form action="">
<input type="radio" name="radio_input" value="1">
<input type="radio" name="radio_input" class="switcher-radio-neutral" value="2">
<input type="radio" name="radio_input" value="3">
</form>
<br><br>
<div class="switcher">
<label class='switcher-label switcher-off' for='off'>off</label>
<input id='off' class='switcher-radio-off' type='radio' name='value' value='off'>
<label class='switcher-label switcher-neutral' for='neutral'>neutral</label>
<input id='neutral' class='switcher-radio-neutral' type='radio' name='value' value='neutral' data-neutral="">
<label class='switcher-label switcher-on' for='on'>on</label>
<input id='on' class='switcher-radio-on' type='radio' name='value' value='on'>
<div class='switcher-slider'></div>
</div>
回答by kay
As HexInteractive mentioned, radio button is handled outside the normal event chain. So, following example judges the button state by class name, not by property.
正如 HexInteractive 所提到的,单选按钮是在正常事件链之外处理的。所以,下面的例子是通过类名而不是属性来判断按钮状态的。
var $self;
$('input[type=radio]').on('click', function() {
$self = $(this);
if ( $self.hasClass('is-checked') ) {
$self.prop('checked', false).removeClass('is-checked');
} else {
$self.addClass('is-checked');
}
});