we have implemented a functionality that after clicking on a button, a section appears having input and search button and when the complete section blurs when navigated using tab key, then the original button comes back. We have added onfocusout event to capture child element blur event, but it is getting triggering separately for each element i.e. when user clicks on input, then press tab key, instead of going to button, it hides the section. We want when the complete div goes out of focus then it gets hidden. Is there a way to achieve this? Also, as the code needs to be written in Angular, so won't we able to use jQuery if there might be some solution using it.
function showButton() {
var x = document.getElementById("searchWithButton");
x.classList.add("display-none");
var y = document.getElementById("search");
y.classList.remove("display-none");
}
function showSearchDiv() {
var x = document.getElementById("searchWithButton");
x.classList.remove("display-none");
var y = document.getElementById("search");
y.classList.add("display-none");
var z = document.getElementById("searchInput");
z.focus();
}
.red-border {
border: 2px solid red;
padding: 5px;
}
.display-none {
display: none;
}
<div id="searchWithButton" onfocusout="showButton()" class="red-border display-none">
<input id="searchInput" type="text">
<button>Search</button>
</div>
<button id="search" onclick="showSearchDiv()">Search</button>
What is the desired behavior to hide the searchWithButton? May I suggest any of the following: a click outside, pressing [escape]. Or focusing another element using [tab] (a little patchy)
var x = document.getElementById("searchWithButton");
var y = document.getElementById("search");
var z = document.getElementById("searchInput");
function showButton() {
x.classList.add("display-none");
y.classList.remove("display-none");
}
function showSearchDiv() {
x.classList.remove("display-none");
y.classList.add("display-none");
z.focus();
}
window.addEventListener('keydown', function(ev) {
if (ev.keyCode==27) {
showButton();
}
})
window.addEventListener('mousedown', function(ev) {
if (!ev.target.closest("#searchWithButton")) {
showButton()
}
})
document.querySelectorAll(".get-focus").forEach(function(item) {
item.addEventListener('focus', showButton)
})
.red-border {
border: 2px solid red;
padding: 5px;
}
.display-none {
display: none;
}
before: <input type="text" name="before" class="get-focus">
<br><br>
<div id="searchWithButton" class="red-border display-none">
<input id="searchInput" type="text">
<button>Search</button>
</div>
<button id="search" onclick="showSearchDiv()">Search</button>
<br><br> after: <input type="text" name="after" class="get-focus">
I would like to be able to click on the whole element, rather than just the radio button and text, in order to register the value associated with the radio button.
<div class='btn'>
<input id = '4' class='btn4' type="radio" name='1' value='' >
<label for = '4' class="label4">Question populated from jQuery goes here
</label></div>
When I wrap the input with the label, I lose the text that jQuery puts inside the element.
The function I have to populate the text is...
function populateQuestion(index) {
if (currentQuestion <=9){
$('.q_question').html(questionsArray[index]['question']);
for (var i = 0; i < 8; i++) {
$('.jumbotron').html('');
$('.btn' + (i + 1)).val(questionsArray[index]['choices'][i]).prop('checked', false);
$('.label' + (i + 1)).html(questionsArray[index]['choices'][i]);
}
} else{ quizComplete(correctAnswers)}
}
populateQuestion(currentQuestion);
Interesting little problem. I tried to do it in one line of jQuery, but quickly realized that since the elements that were changing we located inside the container, trying to click them would reset them (effectively making themselves unclickable). The solution was to add an invisible pseudo element on top of the container in CSS so that you couldn't actually click the radio (or label).
$('div.btn').on('click', function() {
$(this).children('input').prop('checked', !$(this).children('input').prop('checked'));
})
.btn {
border: 1px solid red;
padding: 12px;
position: relative;
}
.btn::after {
content: "";
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='btn'>
<input id='4' class='btn4' type="radio" name='1' value=''>
<label for='4' class="label4">Question populated from jQuery goes here
</label>
</div>
You may register a click event for the outer div and execute whatever code you want to do .
$(function(){
$("div.btn").click(function(e){
e.preventDefault();
alert("clicked");
var _this=$(this);
var radio = _this.find("input[type='radio']");
//Do something now
alert('id:'+radio.attr("id")); //Id of radio button
alert('value:'+radio.val()); //value of radio button
});
});
Here is a working sample.
I have a page with two areas. There are boxes in each area. If the user clicks on a box in the top area, it gets moved to the bottom and vice versa. This works fine for the first movement. Theoretically, I should be able to move them back and forth between sections as I please.
Box HTML:
<div id="top-area">
<div class="top-box" id="blue-box"></div>
<div class="top-box" id="yellow-box"></div>
<div class="top-box" id="green-box"></div>
</div>
<hr/>
<div id="bottom-area">
<div class="bottom-box" id="red-box"></div>
<div class="bottom-box" id="gray-box"></div>
</div>
I use jQuery.remove() to take it out of the top section and jQuery.append() to add it to the other. However, when I try to move a box back to its original position, the event that I have created to move them doesn't even fire.
jQuery/JavaScript:
$(".top-box").on('click', function ()
{
var item = $(this);
item.remove();
$(this).removeClass("top-box").addClass("bottom-box");
$("#bottom-area").append(item);
});
$(".bottom-box").on('click', function ()
{
var item = $(this);
item.remove();
$(this).removeClass("bottom-box").addClass("top-box");
$("#top-area").append(item);
});
I have verified that the classes I am using as jQuery selectors are getting added/removed properly. I am even using $(document).on() to handle my event. How come my boxes are not triggering the jQuery events after they are moved once?
Please see the Fiddle: http://jsfiddle.net/r6tw9sgL/
Your code attaches the events on the page load to the elements that match the selector right then.
If you attach the listener to #top-area and #bottom-area and then use delegated events to restrict the click events to the boxes, it should work like you expect. See .on: Direct and Delegated Events for more information.
Use the below JavaScript:
$("#top-area").on('click', '.top-box', function ()
{
var item = $(this);
item.remove();
$(this).removeClass("top-box").addClass("bottom-box");
$("#bottom-area").append(item);
});
$("#bottom-area").on('click', '.bottom-box', function ()
{
var item = $(this);
item.remove();
$(this).removeClass("bottom-box").addClass("top-box");
$("#top-area").append(item);
});
Alternatively:
You could also change .on() to .live(), which works for "all elements which match the current selector, now and in the future." (JSFiddle)
JSFiddle
Here's another way you could work it:
function toBottom ()
{
var item = $(this);
item.remove();
item.off('click', toBottom);
item.on('click', toTop);
$(this).removeClass("top-box").addClass("bottom-box");
$("#bottom-area").append(item);
}
function toTop ()
{
var item = $(this);
item.remove();
item.off('click', toTop);
item.on('click', toBottom);
$(this).removeClass("bottom-box").addClass("top-box");
$("#top-area").append(item);
}
$(".top-box").on('click', toBottom);
$(".bottom-box").on('click', toTop);
#top-area, #bottom-area {
height: 100px;
border: 1px solid black;
padding: 10px;
}
.top-box::before {
content: "Top";
}
.bottom-box::before {
content: "Bottom";
}
#blue-box, #red-box, #yellow-box, #green-box, #gray-box {
width: 100px;
cursor: pointer;
float: left;
margin: 0 5px;
text-align: center;
padding: 35px 0;
}
#blue-box {
background-color: blue;
}
#red-box {
background-color: red;
}
#yellow-box {
background-color: yellow;
}
#green-box {
background-color: green;
}
#gray-box {
background-color: gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="top-area">
<div class="top-box" id="blue-box"></div>
<div class="top-box" id="yellow-box"></div>
<div class="top-box" id="green-box"></div>
</div>
<hr/>
<div id="bottom-area">
<div class="bottom-box" id="red-box"></div>
<div class="bottom-box" id="gray-box"></div>
</div>
This basically removes the listener that switched the object to bottom to a listener that switches the object to the top and viceversa.
I've a web application with dialogs. A dialog is a simple div-container appended to the body. There is also an overlay for the whole page to prevent clicks to other controls. But: Currently the user can focus controls that are under the overlay (for example an input). Is there any way to limit the tabbable controls to those which are in the dialog?
I am using jQuery (but not using jQueryUI). In jQueryUi dialogs it's working (but I don't want to use jQueryUI). I failed to figure out, how this is accomplished there.
Here is the jQueryUI example: http://jqueryui.com/resources/demos/dialog/modal-confirmation.html - The link on the webpage is not focusable. The focus is kept inside the dialog (the user cannot focus the urlbar of the browser using tab).
HTML:
I should not receive any focus
<input type="text" value="No focus please" />
<div class="overlay">
<div class="dialog">
Here is my dialog<br />
TAB out with Shift+Tab after focusing "focus #1"<br />
<input type="text" value="focus #1" /><br />
<input type="text" value="focus #1" /><br />
</div>
</div>
CSS:
.overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.3);
text-align: center;
}
.dialog {
display: inline-block;
margin-top: 30%;
padding: 10px;
outline: 1px solid black;
background-color: #cccccc;
text-align: left;
}
Here is my fiddle: http://jsfiddle.net/SuperNova3000/weY4L/
Does anybody have an idea? I repeat: I don't want to use jQueryUI for this. I'd like to understand the underlying technique.
I've found an easy solution for this issue after hours of trying. I think the best way is adding 2 pseudo elements. One before and one after the dialog (inside the overlay). I'm using <a>-Tags which are 0x0 pixels. When reaching the first <a>, I'm focusing the last control in the dialog. When focusing the last <a>, I'm focusing the first control in the dialog.
I've adapted the answer of this post: Is there a jQuery selector to get all elements that can get focus? - to find the first and last focusable control.
HTML:
<div class="overlay">
<a href="#" class="focusKeeper">
<div class="dialog">
Here is my dialog<br />
TAB out with Shift+Tab after focusing "focus #1"<br />
<input type="text" value="focus #1" /><br />
<input type="text" value="focus #1" /><br />
</div>
<a href="#" class="focusKeeper">
</div>
Extra CSS:
.focusKeeper {
width: 0;
height: 0;
overflow: hidden;
}
My Javascript:
$.fn.getFocusableChilds = function() {
return $(this)
.find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object:not([disabled]), embed, *[tabindex], *[contenteditable]')
.filter(':visible');
};
[...]
$('.focusKeeper:first').on('focus', function(event) {
event.preventDefault();
$('.dialog').getFocusableChilds().filter(':last').focus();
});
$('.focusKeeper:last').on('focus', function(event) {
event.preventDefault();
$('.dialog').getFocusableChilds().filter(':first').focus();
});
May be I'll add a fiddle later, no more time for now. :(
EDIT: As KingKing noted below the focus is lost, when clicking outside the control. This may be covered by adding an mousedown handler for the .overlay:
$('.overlay').on('mousedown', function(event) {
event.preventDefault();
event.stopImmediatePropagation();
});
EDIT #2: There's another thing missing: Going outside the document with the focus (for example the titlebar) and than tabbing back. So we need another handler for document which puts back the focus on the first focusable element:
$(document).on('focus', function(event) {
event.preventDefault();
$('.dialog').getFocusableChilds().filter(':first').focus();
});
You can try handling the focusout event for the .dialog element, check the e.target. Note about the e.relatedTarget here, it refers to the element which receives focus while e.target refers to the element lossing focus:
var tabbingForward = true;
//The body should have at least 2 input fields outside of the dialog to trap focusing,
//otherwise focusing may be outside of the document
//and we will loss control in such a case.
//So we create 2 dummy text fields with width = 0 (or opacity = 0)
var dummy = "<input style='width:0; opacity:0'/>";
var clickedOutside = false;
$('body').append(dummy).prepend(dummy);
$('.dialog').focusout(function(e){
if(clickedOutside) {
e.target.focus();
clickedOutside = false;
}
else if(!e.relatedTarget||!$('.dialog').has(e.relatedTarget).length) {
var inputs = $('.dialog :input');
var input = tabbingForward ? inputs.first() : inputs.last();
input.focus();
}
});
$('.dialog').keydown(function(e){
if(e.which == 9) {
tabbingForward = !e.shiftKey;
}
});
$('body').mousedown(function(e){
if(!$('.dialog').has(e.target).length) {
clickedOutside = true;
}
});
Demo.
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.
This is not to 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.
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
try this:
$('input[type=radio]').click(function(){
if (this.previous) {
this.checked = false;
}
this.previous = this.checked;
});
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.
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:
$("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");
});
http://jsfiddle.net/bhzako65/
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.
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
<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
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>
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!
Found this somewhere while looking for a solution, do like the simplicity of it...
var checkedradio;
function docheck(thisradio) {
if (checkedradio == thisradio) {
thisradio.checked = false;
checkedradio = null;
}
else {checkedradio = thisradio;}
}
Use with:
<input type='radio' onclick='docheck(this);'>
It does seem to require a double click to deselect when you have multiple radio groups in a form though, but this could by solved by having a function for each group I suppose...
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.
See fiddle at http://jsfiddle.net/ArktekniK/yhbw469f/
For toggling a radio button by clicking on the radio button itself
$('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;
});
Who those who are seeking for a pure JavaScript solution I modified the code from Jase in ATL's answer.
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).
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>
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.
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:
http://www.nngroup.com/articles/checkboxes-vs-radio-buttons/
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.
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');
}
});
Based on answer by Stephen - this deals with multiple radio button groups and also you mostly don't need to double click radio buttons. It isn't perfect as if you switch between groups the check for id will necessitate an extra click but works ok.
$("input[type='radio']").on('click', function (e) {
if (this.previous && this.value == previousvalue && this.id == previousid) {
this.checked = false;
}
this.previous = this.checked;
previousvalue = this.value;
previousid = this.id;
});
Yes you can also do this on click checked, again click uncheck.
Here is the logic of this:
$('input[name=check1]').prop('checked',!$('input[name=check1]').prop('checked'));
var checked = {};
$('.desectable-radio').each(function (index) {
checked[index] = this.checked;
$(this).click(function () {
if (checked[index])
this.checked = false;
for (var i in checked) {
checked[i] = false;
}
checked[index] = this.checked;
});
});
Here's a super lightweight script you can add to a page through the console window that allows you to deselect a radio button by holding down Ctrl while clicking it with the mouse.
document.addEventListener('click', function(e){
if (e.ctrlKey == true &&
e.target.tagName == 'INPUT' &&
e.target.type == "radio" &&
e.target.checked == true) {
e.target.checked = false;
}
});
Since it doesn't rely on jQuery, you can easily add it to any page to temporarily allow deselection.
For slightly more info, you can read an article I just wrote on How To Deselect A Radio Button.
Needing a solution to this issue, I settled on replacing the currently active radio button with a ‘cancel’ icon button, like this http://fontawesome.io/icon/ban/
Clicking this icon unchecked the active radio button, which then reappeared, effectively resetting the radio button group. The cancel icon was also removed from the DOM.
Alternatively the user could click another of the radio buttons in the group, which would behave as normal aside from the cancel button, which was then ‘moved’ to replace the new active radio button.
This kept the cancel icon in an intuitive location (i.e. where the user last clicked) and was safer than assuming the user would know to re-click the currently active radio button to deactivate the group.
Worst case if you have a long list of radio buttons, the user just has to click any of them twice to clear the group.
I think this is the shortest way. I tested it on Chrome and MS Edge.
$(document).on('click', 'input:radio', function () {
var check = $(this).attr('checked')
if (check) $(this).removeAttr('checked').prop('checked',false)
else $(this).attr('checked', true).prop('checked',true)
})
This piece of code also works on AJAX loaded contents.
Using prop function with checked as key:
$("input:radio").prop("checked",false);
This should work for desktop and mobile. I tested on Chrome and Firefox.
Based on the highest rated answer, but using newer JQuery and alot simpler implementation using $.one.
$(':radio').on("mousedown touchstart", function (e) {
var mobile = true;
if(e.type.toLowerCase() === 'mousedown'){
mobile = false;
}
var $self = $(this);
if($self.prop('checked')){
var uncheck = function(){
setTimeout(function(){
$self.prop('checked',false);
},10);
};
if(!mobile){
$self.one('mouseup', uncheck);
} else {
$self.one('touchstart', uncheck);
}
}
});
<script type="text/javascript">
$( document ).ready(function() {
$('input[type=radio]').click(function(){
if (this.previous) {
this.checked = false;
document.getElementById("nc").style.display = "block";
this.previous=false;
}
else {
this.previous = this.checked;
document.getElementById("nc").style.display = "none";
}
});
});
</script>
A javascript version featuring deselection via the for label and no double clicks.
The temporary state is attached to a parent div.
Parent.onclick = e => {
rb = e.target;
if (rb.type == "radio") {
if (Parent.rb == rb) {
rb.checked = false;
Parent.rb = null;
} else {
Parent.rb = rb
}
}
}
<div id="Parent">
<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>
</div>
A pure css solution (without javascript)
label > input:checked,
label > input:checked + label {
pointer-events: none;
}
#unselect {
display: none;
}
<input type="radio" name="foo" id="unselect">
<label for="unselect">
<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>
</label>
The radiobuttons are embedded into another radiobutton.
When a radiobutton is selected, it doesn't accepted clicks anymore, instead the underlying radiobutton captures the click.
https://jsfiddle.net/w29rem7q/
original, now obsolete solution
To each radio button a dummy radio button is attached. If a radio button is selected, an invisible dummy will be above the radio button to catch the next click.
input:not([id^=foo]) {
opacity: 0.0;
}
input[id^=foo]:checked {
position: absolute;
}
input[id^=foo]:not(:checked) + input {
display: none;
}
<input type="radio" name="foo" id="foo1">
<input type="radio" name="foo">
<label for="foo1">foo1</label>
<input type="radio" name="foo" id="foo2">
<input type="radio" name="foo">
<label for="foo2">foo2</label>
<input type="radio" name="foo" id="foo3">
<input type="radio" name="foo">
<label for="foo3">foo3</label>
Likely just for fun, while in practice js will be easier to maintain.
Also deselection via label click, would be more work arounds.