如何使一个单选按钮不被选中通过点击它?

与复选框不同,用户不可能在单选按钮被单击后取消选择。有没有什么方法可以使用 Javascript 以编程的方式切换它们?最好不要使用 jQuery。

348143 次浏览

You can set HTML object's property checked to false like this:

document.getElementById('desiredInput').checked = false;

Examples

Plain JavaScript:

var radios = document.getElementsByTagName('input');
for(i=0; i<radios.length; i++ ) {
radios[i].onclick = function(e) {
if(e.ctrlKey || e.metaKey) {
this.checked = false;
}
}
}
<input type="radio" name="test" value="1" />
<input type="radio" name="test" value="2" checked="checked" />
<input type="radio" name="test" value="3" />

jQuery:

$('input').click(function(e){
if (e.ctrlKey || e.metaKey) {
$(this).prop('checked', false);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="radio" name="test" value="1" />
<input type="radio" name="test" value="2" checked="checked" />
<input type="radio" name="test" value="3" />

Hold down Ctrl ( on mac) key to uncheck.

Radio buttons are meant to be used in groups, as defined by their sharing the same name attribute. Then clicking on one of them deselects the currently selected one. To allow the user to cancel a “real” selection he has made, you can include a radio button that corresponds to a null choice, like “Do not know” or “No answer”.

If you want a single button that can be checked or unchecked, use a checkbox.

It is possible (but normally not relevant) to uncheck a radio button in JavaScript, simply by setting its checked property to false, e.g.

<input type=radio name=foo id=foo value=var>
<input type=button value="Uncheck" onclick=
"document.getElementById('foo').checked = false">

You could use the checked property of a radio button to uncheck it.

Something like this:

<script>
function uncheck()
{
document.getElementById('myRadio').checked = false;
}
function check()
{
document.getElementById('myRadio').checked = true;
}
</script>
<input id="myRadio" type="radio" checked="checked"/>
<button onclick="uncheck();">Uncheck</button>
<button onclick="check();">Check</button>

​See it in action here: http://jsfiddle.net/wgYNa/

The full code will look something like this

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>


<body>
<input name="radio" type="radio" id="myRadio" value="myRadio" checked="checked"     onclick="setRadio(this)" />
<label for="myRadio"></label>




<script language="javascript">
function setRadio(obj)
{
obj.checked = false;
}
</script>
</body>
</html>

Here's an example of where it is arguably appropriate to uncheck radio buttons other than by making a new selection. I have a dictionary whose entries can be selected using a variety of indices. Which index to use is selected by means of a set of radio buttons. However, there is also a "random entry" button that the user can use if he or she just wants to browse. Leaving an index in place when the entry has been selected by means of the random entry button would be misleading, so when this button is pressed, I uncheck all of the index selection radio buttons and replace the contents of the index frame with an empty page.

As radio button mostly used in group, its a lot easier to grab them by getElementsByName( ' ' ); in your script tag. This will return an array, put an event listener on each array child and set the check state. Look at this sample.

var myRadios = document.getElementsByName('subscribe');
var setCheck;
var x = 0;
for(x = 0; x < myRadios.length; x++){


myRadios[x].onclick = function(){
if(setCheck != this){
setCheck = this;
}else{
this.checked = false;
setCheck = null;
}
};


}

This guide explain how the code works with a visual demonstration.

That's what I came to:

function uncheck_radio_before_click(radio) {
if(radio.prop('checked'))
radio.one('click', function(){ radio.prop('checked', false); } );
}
$('body').on('mouseup', 'input[type="radio"]', function(){
var radio=$(this);
uncheck_radio_before_click(radio);
})
$('body').on('mouseup', 'label', function(){
var label=$(this);
var radio;
if(label.attr('for'))
radio=$('#'+label.attr('for')).filter('input[type="radio"]');
else
radio=label.children('input[type="radio"]');
if(radio.length)
uncheck_radio_before_click(radio);
})

http://jsfiddle.net/24vft2of/2/

This is my answer (though I made it with jQuery but only for the purpose of selecting elements and to add and remove a class, so you can easily replace it with pure JS selectors & pure JS add attribute )

<input type='radio' name='radioBtn'>
<input type='radio' name='radioBtn'>
<input type='radio' name='radioBtn'>


$(document).on("click", "input[name='radioBtn']", function(){
thisRadio = $(this);
if (thisRadio.hasClass("imChecked")) {
thisRadio.removeClass("imChecked");
thisRadio.prop('checked', false);
} else {
thisRadio.prop('checked', true);
thisRadio.addClass("imChecked");
};
})

Wrapped up in a plugin

Limitations:

  1. Require form element
  2. Must trigger click event when changing radio button programmatically

(function($) {
$.fn.uncheckableRadio = function() {
var $root = this;
$root.each(function() {
var $radio = $(this);
if ($radio.prop('checked')) {
$radio.data('checked', true);
} else {
$radio.data('checked', false);
}
        

$radio.click(function() {
var $this = $(this);
if ($this.data('checked')) {
$this.prop('checked', false);
$this.data('checked', false);
$this.trigger('change');
} else {
$this.data('checked', true);
$this.closest('form').find('[name="' + $this.prop('name') + '"]').not($this).data('checked', false);
}
});
});
return $root;
};
}(jQuery));


$('[type=radio]').uncheckableRadio();
$('button').click(function() {
$('[value=V2]').prop('checked', true).trigger('change').trigger('click');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form>
<label><input name="myRadio" type="radio" value="V1" /> R1</label>
<label><input name="myRadio" type="radio" value="V2" /> R2</label>
<label><input name="myRadio" type="radio" value="V3" /> R3</label>
<button type="button">Change R2</button>
</form>

Extending user3716078's answer to allow multiple independent radio button groups and a neater way of assigning event listeners to multiple elements...

window.onload = function() {


var acc_checked=[];


[].slice.call(document.querySelectorAll('.accordion input[type="radio"]')).forEach(function(el,i){
/**
* i represents the integer value of where we are in the loop
* el represents the element in question in the current loop
*/
el.addEventListener('click', function(e){


if(acc_checked[this.name] != this) {
acc_checked[this.name] = this;
} else {
this.checked = false;
acc_checked[this.name] = null;
}


}, false);


});


}

I came here because I had the same issue. I wanted to present the options to the user while leaving the option of remaining empty. Although this is possible to explicitly code using checkboxes that would complicate the back end.

Having the user Control+click is almost as good as having them uncheck it through the console. Catching the mousedown is to early and onclick is too late.

Well, at last here is a solution! Just put these few lines once on the page and you have it made for all radio buttons on the page. You can even fiddle with the selector to customize it.

window.onload = function() {
document.querySelectorAll("INPUT[type='radio']").forEach(function(rd) {
rd.addEventListener("mousedown", function() {
if(this.checked) {
this.onclick=function() {
this.checked=false
}
} else {
this.onclick=null
}
})
})
}
<input type=radio name=unchecksample> Number One<br>
<input type=radio name=unchecksample> Number Two<br>
<input type=radio name=unchecksample> Number Three<br>
<input type=radio name=unchecksample> Number Four<br>
<input type=radio name=unchecksample> Number Five<br>

while it was asked in terms of javascript, the adaption from jquery is trivial... with this method you can check for the "null" value and pass it...

var checked_val = "null";
$(".no_option").on("click", function(){
if($(this).val() == checked_val){
$('input[name=group][value=null]').prop("checked",true);
checked_val = "null";
} else {
checked_val = $(this).val();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="radio" name="group" class="no_option" value="0">option 0<br>
<input type="radio" name="group" class="no_option" value="1">option 1<br>
<input type="radio" name="group" class="no_option" value="2">option 2<br>
<input type="radio" name="group" class="no_option" value="3">option 3<br>
<input type="radio" name="group" class="no_option" value="4">option 4<br>
<input type="radio" name="group" class="no_option" value="5">option 5<br>
<input type="radio" name="group" class="no_option" value="6">option 6<br>
<input type="radio" name="group" class="no_option" value="null" style="display:none">

If you use Iclick pluging, it is as simply as you see below.

 $('#radio1').iCheck('uncheck');

In the radio button object creation code include these three lines:

  obj.check2 = false;    // add 'check2', a user-defined object property
obj.onmouseup = function() { this.check2 = this.checked };
obj.onclick = function() { this.checked = !this.check2 };

Unfortunately it does not work in Chrome or Edge, but it does work in FireFox:

$(document)
// uncheck it when clicked
.on("click","input[type='radio']", function(){ $(this).prop("checked",false); })
// re-check it if value is changed to this input
.on("change","input[type='radio']", function(){ $(this).prop("checked",true); });

Full example in pure JavaScript :

box.onmouseup = function() {
var temp = this.children[0];
if (temp.checked) {
setTimeout(function() {
temp.checked = false;
}, 0);
}
}
<label id='box' style='margin-right: 1em;'>
<input type='radio' name='chk_préf_méd_perso' value='valeur'>
libellé
</label>

Old question but people keep coming from Google here and OP asked preferably without jQuery, so here is my shot.

Should works even on IE 9

// iterate using Array method for compatibility
Array.prototype.forEach.call(document.querySelectorAll('[type=radio]'), function(radio) {
radio.addEventListener('click', function(){
var self = this;
// get all elements with same name but itself and mark them unchecked
Array.prototype.filter.call(document.getElementsByName(this.name), function(filterEl) {
return self !== filterEl;
}).forEach(function(otherEl) {
delete otherEl.dataset.check
})


// set state based on previous one
if (this.dataset.hasOwnProperty('check')) {
this.checked = false
delete this.dataset.check
} else {
this.dataset.check = ''
}
}, false)
})
<label><input type="radio" name="foo" value="1"/>foo = 1</label><br/>
<label><input type="radio" name="foo" value="2"/>foo = 2</label><br/>
<label><input type="radio" name="foo" value="3"/>foo = 3</label><br/>
<br/>
<label><input type="radio" name="bar" value="1"/>bar = 1</label><br/>
<label><input type="radio" name="bar" value="2"/>bar = 2</label><br/>
<label><input type="radio" name="bar" value="3"/>bar = 3</label><br/>

A working bug free update to Shmili Breuer answer.

(function() {
$( "input[type='radio'].revertible" ).click(function() {
var $this = $( this );


// update and remove the previous checked class
var $prevChecked = $('input[name=' + $this.attr('name') + ']:not(:checked).checked');
$prevChecked.removeClass('checked');


if( $this.hasClass("checked") ) {
$this.removeClass("checked");
$this.prop("checked", false);
}
else {
$this.addClass("checked");
}
});
})();

This almost worked for me.

<input type='radio' name='radioBtn'>
<input type='radio' name='radioBtn'>
<input type='radio' name='radioBtn'>


$(document).on("click", "input[name='radioBtn']", function(){
thisRadio = $(this);
if (thisRadio.hasClass("imChecked")) {
thisRadio.removeClass("imChecked");
thisRadio.prop('checked', false);
} else {
thisRadio.prop('checked', true);
thisRadio.addClass("imChecked");
};
})

But If I check a radio button, then check another and try to check the first one again I must do two clicks. This is because it has the class imChecked. I just needed to uncheck the other radio buttons before the verification.

Add this line makes it work:

$("input[name='radioBtn']").not(thisRadio).removeClass("imChecked");

<input type='radio' name='radioBtn'>
<input type='radio' name='radioBtn'>
<input type='radio' name='radioBtn'>


$(document).on("click", "input[name='radioBtn']", function(){
thisRadio = $(this);
$("input[name='radioBtn']").not(thisRadio).removeClass("imChecked");
if (thisRadio.hasClass("imChecked")) {
thisRadio.removeClass("imChecked");
thisRadio.prop('checked', false);
} else {
thisRadio.prop('checked', true);
thisRadio.addClass("imChecked");
};
})

The code below will do the trick.

$('input[type=radio]').click(function() {
if($(this).hasClass("checked")){
this.checked = false;
$(this).removeClass("checked")
}else{
$(this).addClass("checked")
}
});

Let's suppose you have a button where on clicking it, you can make all your radio button selection to false. You can write the below code inside the onclick handler.
Below code take radio buttons based on class name and for each element it will mark it to false.

var elements=document.getElementsByClassName('Button');


Array.prototype.forEach.call(elements, function(element) {
element.checked = false;
});

How unchecking radio does (not) work

You cannot easily implement uncheck trivially via if(this.checked) this.checked = false, (if you really want to, see the hacker way at the end) because the events fire in this order:

  1. mousedown or keydown
  2. mouseup or keyup
  3. if not checked, set the checked property now
  4. click
  5. input (only if state is changed)
  6. change (only if state is changed)

Now in which event to perform the mentioned uncheck?

  • mouseup or mousedown: then in the step 3 the value is set back to true and change and input event doesn't even fire as the state didn't change when they are called in the sequence - so you can't uncheck it here
  • click: then the state is always false and input and change also doesn't fire - so you can't check it
  • input or change: it doesn't fire when the state is not changed and clicking selected element doesn't change the state - so you can't do anything useful here

The naive way

As you can learn from the sequence above, the way is:

  1. read the previous state in mouseup
  2. set the state in click as negation of previous state

If you want to store the previous state in data attribute, keep in mind that it is saved as string, whereas the checked attribute is boolean. So you can implement it like:

radio.onmouseup = function() { this.dataset.checked = this.checked? 1 : ""; }
radio.onclick = function() { this.checked = !this.dataset.checked; }

It seemingly works, but you should not do this for these reasons:

  • the user may mousedown somewhere else, then hover above radio button, then mouseup: in this case mouseup fires and click does not
  • the user may use Tab to focus radio group, then arrows to change: mouseup doesn't fire and click does

The proper way

There is another issue: dynamically added radio buttons. There are two ways:

  1. element.appendChild(radio) - if you enable deselect on all radios in DOMContentLoaded event, this dynamically added radio is not affected
  2. element.innerHTML+= '<input type="radio">' - effectively replaces the HTML contents of the element and re-creates DOM inside it - so all event listeners are discarded

To solve (2), I recommend onclick content attribute. Note that element.onclick = fn and element.setAttribute("onclick", "fn()") are two different things. Also note that onclick fires everytime the user activates the radio, regardless of the interface he used.

Yet another issue: if you enable deselect, then you should also enable switching by Space to mimic checkboxes behaviour. The following code solves all mentioned issues:

function deselectableRadios(rootElement) {
if(!rootElement) rootElement = document;
if(!window.radioChecked) window.radioChecked = {};
window.radioClick = function(e) {
const obj = e.target, name = obj.name || "unnamed";
if(e.keyCode) return obj.checked = e.keyCode!=32;
obj.checked = window.radioChecked[name] != obj;
window.radioChecked[name] = obj.checked ? obj : null;
}
rootElement.querySelectorAll("input[type='radio']").forEach( radio => {
radio.setAttribute("onclick", "radioClick(event)");
radio.setAttribute("onkeyup", "radioClick(event)");
});
}


deselectableRadios();
<label><input type="radio" name="tag1">one</label>
<label><input type="radio" name="tag1">two</label>
<label><input type="radio" name="tag1">three</label>


<br><br>


<label><input type="radio" name="tag2">one</label>
<label><input type="radio" name="tag2">two</label>
<label><input type="radio" name="tag2">three</label>

Now you can call deselectableRadios() anytime you dynamically add content and calling it on radios multiple times doesn't break it. You can also specify the rootElement to update only a subtree of HTML DOM and make your web faster. If you don't like the global state, you can use the hacker way:

The hacker way

The point is to abuse setTimeout on mouseup to call it after the checked property is set:

function deselectable() {
setTimeout(checked => this.checked = !checked, 0, this.checked);
}

Now you can make any radio button deselectable:

radio.onmouseup = deselectable;

But this simple one-liner works just with clicking and doesn't solve the issues mentioned above.

The abandoned future

Deselectable radio is basically checkbox where only one in the group can be checked. There was a promising straightforward hope to code it as

<input type="checkbox" name="foo" style="appearance: radio">

However, the radio value is now defined as compat-auto type which is treated like auto, i.e. no visual change. It seems that there will be no progress here in the future.

I will try to make a small answer with 3 radio buttons, you can add stuff later on.

const radios = Array.from(document.getElementsByClassName('radio'))


for(let i of radios) {
i.state = false


i.onclick = () => {
i.checked = i.state = !i.state


for(let j of radios)
if(j !== i) j.checked = j.state = false
}
}
<input class="radio" type="radio">X
<input class="radio" type="radio">Y
<input class="radio" type="radio">Z
This works for single form. If you have multiple form with the class="radio", then once you click on a radio button, the others are disabled. Use this if that's what you want.


Now I wanted to implement this on my rails project, which has multiple forms (depends, fetched from database), each form has 2 visible radio buttons + 1 hidden radio button.

I want the user the select / deselect the radio button of each form. And selecting one on a form shouldn't deselect the other selected button on another form. So I rather did this:

var radios = Array.from(document.getElementsByClassName('radio'))


for (let i of radios) {
i.state = false


i.onclick = () => {
i.checked = i.state = !i.state


for (let j of radios)
if (j !== i) j.state = false
}
}
<form>
<input class="radio" name="A" type="radio">A
<input class="radio" name="A" type="radio">B
<input class="radio" name="A" type="radio">C
</form>


<form>
<input class="radio" name="A" type="radio">D
<input class="radio" name="A" type="radio">E
<input class="radio" name="A" type="radio">F
</form>


<form>
<input class="radio" name="SOMETHING" type="radio">G
<input class="radio" name="SOMETHING" type="radio">H
<input class="radio" name="SOMETHING" type="radio">I
</form>

You see all have the same name, but they are in a different forms, grouped by 3, so this works for multiple forms.

Most of the modern day browsers consider checked="anything" as checked="true".

You might have to remove the checked attribute if that makes sense in your case, one of which might be related to when you load the page.

$(this).removeAttr('checked')

This might help you in cases when you want your radio button to be checked adhering to some condition. You can simply remove the attribute to achieve that.

PS: Not helpful in all the cases.

Here is the way for plain JS, which onchange and onclick events are combined (onchange for checking while onclick for unchecking).

document.querySelector("input").onchange = function() {
this.onclick = function() {
this.checked = false;
this.onclick = null;
}
};

If you are looking for solution in jQuery here it is. It is similar to this

    $('input:radio').click(function() {
let name = $(this).attr('name');
let self = $(this);
[].filter.call($(`input[name=${name}]`), function(ele){
return self[0] !== $(ele)[0];
}).forEach(function(otherEle){
$(otherEle).removeAttr('data-check');
});


if($(this).attr('data-check')){
$(this).prop("checked", false);
$(this).removeAttr('data-check');
}else{
$(this).attr("data-check", "1");
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<input class="radio" name="A" type="radio">A
<input class="radio" name="A" type="radio">B
<input class="radio" name="A" type="radio">C
</form>


<form>
<input class="radio" name="B" type="radio">D
<input class="radio" name="B" type="radio">E
<input class="radio" name="B" type="radio">F
</form>


<form>
<input class="radio" name="C" type="radio">G
<input class="radio" name="C" type="radio">H
<input class="radio" name="C" type="radio">I
</form>

I'm surprised no-one has posted this "neat trick" version which doesn't use any JavaScript, it only uses CSS.

#radio1 {
display: none;
}


#wrapper {
/* NOTE: This wrapper div is not needed provided you can position the label for #radio1 on top of #radio2 using some other technique. */
position: relative;
}


#radio1:not(:checked) ~ * label[for="radio1"] {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
#radio1:checked ~ * label[for="radio1"] {
display: none;
}


/* Non-essential styles: */


label[for],
label:not([for="radio1"]) {
cursor: pointer;
border-radius: 7px;
}
label[for]:hover + label,
label:not([for="radio1"]):hover {
background-color: #ccc;
}
<input type="radio" name="group1" id="radio1" checked="checked"  />


<p>Look mum, <strong>no JavaScript!</strong></p>


<div id="wrapper">
<label for="radio1"></label>
<label>
<input type="radio" name="group1" id="radio2" />
You can toggle me on and off!
</label>
</div>


Explanation:

  • #radio1 (<input type="radio" id="radio2" />) is always hidden.
  • Using CSS's :checked and :not(:checked) pseudo-class selectors with sibling selectors (+ and ~) allow other elements' style to be affected depending on whether or not an <input type="checkbox" /> or <input type="radio" /> is checked.
    • So when #radio1 is un-checked (or when #radio2 is checked) that causes a <label> to be overlayed on-top of #radio2 and that label has for="radio1", so clicking it will cause #radio1 to be checked, not #radio2.
    • IMPORTANT CAVEAT: CSS's sibling selector rules only allows selectors to select elements based on their ancestors and their ancestors earlier siblings. So you cannot style an element based on any other descendants of its ancestors.
      • This limitation will be removed when CSS4's :has() selector function is supported but as of November 2020 only PrinceXML supports :has() and it's currently looking like :has() will be dropped from CSS4 entirely owing to the difficulty of implementation.

This approach can be scaled to support multiple radio buttons:

#uncheckAll {
display: none;
}


#uncheckAll:checked ~ * label[for="uncheckAll"] {
display: none;
}


label {
cursor: pointer;
}


label:not([for]) {
position: relative;
}


label[for="uncheckAll"] {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}


input[name="group1"]:not(:checked) + label[for="uncheckAll"] {
display: none;
}
<input type="radio" name="group1" id="uncheckAll" checked="checked"  />


<label>
<input type="radio" name="group1" id="radio2" />
<label for="uncheckAll"></label>
You can toggle me on and off!
</label>


<label>
<input type="radio" name="group1" id="radio3" />
<label for="uncheckAll"></label>
And me!
</label>


<label>
<input type="radio" name="group1" id="aragorn" />
<label for="uncheckAll"></label>
And my sword!
</label>


<label>
<input type="radio" name="group1" id="gimli" />
<label for="uncheckAll"></label>
And my axe!
</label>

I know It's very late (even unnecessary now) and there are many solutions here, but I couldn't find any specific to the question asked or there is so much code in them for this simple scenario, one can easily ignore it while looking for an answer.

So here, I am proposing my solution as It might help any newcomer. The idea is simple, just

  • Set the same class on required toggles in my case its "toggles"
  • Get the current value of the toggle on mouse hover action
  • Inverse the toggle value.

By this either you can select any of the toggles or completely ignores them but clicking again on the already selected toggle. You can also test this with the given snippet.

var val;
$('.toggles').mouseup(function(){
val = this.checked
}).click(function(){
this.checked = val == true ? false : true
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-group">
<input class="toggles form-check-input" type="radio" value="true" name="enabled" id="enabled_true">
<label class="form-check-label" for="enabled_true">Enabled</label>
<input class="toggles form-check-input" type="radio" value="false" name="enabled" id="enabled_false">
<label class="form-check-label" for="enabled_false">Disabled</label>
</div>

This javascript facilitates deselection for each radio in the document:

function toggleRadio(event)
{
if(event.target.type === 'radio' && event.target.checked === true)
{
setTimeout(()=>{ event.target.checked = false; },0);
}
}
document.addEventListener('mouseup', toggleRadio);
body { font-size: .55em; }
table { border-collapse: collapse; margin: 0 auto; }
td, th { border: 1px solid #333333; }
td:first-child { padding: 0 0.7em; }
#scale { font-weight:bold; text-align:center; }
<p id="scale">
5 = Excellent | 4 = Satisfactory | 3 = About Average | 2 = Unsatisfactory | 1 = Very Poor
</p>
<table>
<thead>
<tr>
<th>&nbsp;</th> <th>5</th> <th>4</th> <th>3</th> <th>2</th> <th>1</th>
</tr>
</thead>
<tbody>
<tr>
<td>How do rate the default behavior of radios inputs in HTML?</td>
<td><input type="radio" name="r1" value="5" required></td>
<td><input type="radio" name="r1" value="4"></td>
<td><input type="radio" name="r1" value="3"></td>
<td><input type="radio" name="r1" value="2"></td>
<td><input type="radio" name="r1" value="1"></td>
</tr>
<tr>
<td>How do rate this code's ability to deselect radios?</td>
<td><input type="radio" name="r2" value="5" required></td>
<td><input type="radio" name="r2" value="4"></td>
<td><input type="radio" name="r2" value="3"></td>
<td><input type="radio" name="r2" value="2"></td>
<td><input type="radio" name="r2" value="1"></td>
</tr>
</tbody>
</table>

Advatages of this approach:

  1. Deselection is achieved by clicking the currently selected radio.
  2. Code doesn't require any DOM searches to acquire the radio elements.
  3. Radio inputs that are programmatically added to the document, after page-load, will also be deselect-able.
  4. Only one event listener is created to service all radios (instead of one for each radio).
  5. Code can be ran before or after page load and it still works the same.

User experience considerations, of this code, are discussed here.

I had this issue and my solution was rather simple, I just made them into checkboxes and when one checkbox was toggled, I deselected all the other checkboxes in the group.

I know it is a bit hacky, and has a large big O complexity (although n is small), but it works! (todo: think of more original names for variables)

$(document).ready(function() {
$("input[name=days]").each((_, el) => {
el.addEventListener("click", function () {
$("input[name=days]").each((_, myEl) => {
if (el != myEl) {
myEl.checked = false;
}
});
// Do other stuff
});
});
});
.radio-selector {
display: inline-flex;
flex-wrap: wrap;
vertical-align: top;
justify-content: center;
align-items: center;
margin: 0 auto;
border: 0;
}
.radio-selector input {
position: absolute !important;
clip: rect(0, 0, 0, 0);
}
.radio-selector label {
margin: 0 1rem 1rem 0;
padding: 0.75rem 1rem;
min-width: 10rem;
font-size: 1.6rem;
border-radius: 2rem;
text-align: center;
color: #333;
border: 1px solid #333;
transition: all 0.3s ease-in-out;
}
.radio-selector label:hover {
background-color: lightpink;
cursor: pointer;
}
.radio-selector input:checked + label {
color: white;
background-color: purple;
border: 1px solid transparent;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


<fieldset class="radio-selector">
<input type="checkbox" id="day-1" name="days" value="1" />
<label for=day-1 class="radio-btn">+- 1 day</label>
<input type="checkbox" id="day-3" name="days" value="3" />
<label for=day-3 class="radio-btn">+- 3 days</label>
<input type="checkbox" id="day-7" name="days" value="7" />
<label for=day-7 class="radio-btn">+- 7 days</label>
</fieldset>

sorry if my answer is already answered but honestly i read them all very quickly because there are so many

i am not so skilled, but i think i found a VERY SIMPLE way to uncheck an already checked radio button just by click it again... just with a global var, a little function, and onclick event

<script>
var lastChecked = null;


function unckeck(myRadio)
{
if ( lastChecked == myRadio )
{
lastChecked = null;
myRadio.checked = false;
}
else
lastChecked = myRadio;
}
</script>


<form>
<input type='radio' name='someCommonName' value='foo' onclick='uncheck(this)'/> foo <br/>
<input type='radio' name='someCommonName' value='bar' onclick='uncheck(this)'/> bar <br/>
<input type='radio' name='someCommonName' value='baz' onclick='uncheck(this)'/> baz <br/>
</form>