I have a couple of checkboxes. When I check one, the other unchecks.
Every time this action happens there is a function that checks if the length of the checkboxes is equal to one.
The expected behavior is: if it's equal to one, the function must continue, if not, it must wait until it is. The thing is that the checkboxes are taking way too much time to uncheck.
So, It just ignores everything and continues...
Here's the function:
function unchecking(){
// Here I uncheck the other checkboxes when a new one gets checked
$('.checkbox').on('change', function() {
$('.checkbox').not(this).prop('checked', false);
});
// Then I loop
$.each($('.checkFiltro:checkbox:checked'), function (i, checkbox){
// I need something like this:
if($('.checkFiltro:checkbox:checked') < 2){
// Continue and do another thing
} else {
// Wait until condition is true
}
});
}
PS: Can't use radio. This ain't my project, and I can't change the structure of it from checkboxes to radio.
As I commented - you don't need to "wait" until the condition is true (that exactly one checkbox is checked). You can test that condition each time the state of any checkbox is changed.
This snippet demonstrates doing that - verbosely telling you in the console what's going on. You will see it say "Run the rest of the code" whenever there is exactly one checkbox checked.
$('input[type=checkbox]').on('change', function(e) {
console.log('\nchanged: ' + this.name + ' is checked: ' + this.checked);
let allChecked = $('input[type=checkbox]:checked');
console.log('number of boxes checked = ' + allChecked.length);
console.log('now unchecking any other checked boxes');
$('input[type=checkbox]').not(this).prop('checked', false);
let nowChecked = $('input[type=checkbox]:checked');
console.log('number of boxes now checked = ' + nowChecked.length);
if (nowChecked.length === 1) {
console.log("Run the rest of the code; here, or call a function")
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
Instructions, other controls, whatever
</div>
<div>
<label for="box1">Box 1</label>
<input type="checkbox" id="box1" name="box1">
<label for="box2">Box 2</label>
<input type="checkbox" id="box2" name="box2">
</div>
<div>
More stuff following the checkboxes
</div>
However ... there will only ever be either zero or one box checked - never two - because of unchecking the other box when one gets checked. (Well I suppose there could be initially be two if both were already checked when your code started running)
I have a fiddle with the "un-check" line commented out where you can see what happens with 0, 1, or 2 boxes checked.
So your problem is basically that your function is returning before all the data has arrived that you want to evaluate.
You can wait for a result by employing a timer structure.
function unchecking(){
$('.checkbox').on('change', function() {
$('.checkbox').not(this).prop('checked', false);
});
var waitInterval = setInterval(function(){
var count = 0 ;
$.each($('.checkFiltro:checkbox:checked'), function (i, checkbox){
count++;
});
if(count > 2){
clearInterval(this);
//do stuff here
}
//the interval will continue to ask for the no of checked boxes until it gets cleared at the if statement
},0);
}
Ps. I have not tested this code, let me know if it does not do what I believe it will do, then I will fix and resend :)
Related
I have 2 checkboxes in my page. First id is "status_1", second id is "status_2"
I want to make that both of them must be selected on page load and always keep one selected, when trying to deselect both.
So for example if "status_1" is selected, "status_2" is not selected and user is trying do deselect "status_1" too, "status_2" select automatically.
Here's a nice welcome gift for a new user on this website :-)
Normally we'd like to see what you have tried yourself, so we have some proof of effort since StackOverflow isn't a free programming service.
This code subscribes to the onchange event of the two checkboxes and checks the other one if both are unchecked. Since the actual logic is the same for each case I have moved it to a function to avoid repeating code.
function checkOther(a, b)
{
if (!a.checked && !b.checked)
b.checked = true;
}
window.addEventListener("load", function () {
var s1 = document.querySelector("input[type='checkbox'][name='status_1']");
var s2 = document.querySelector("input[type='checkbox'][name='status_2']");
s1.addEventListener("change", function (e) {
checkOther(e.target, s2);
});
s2.addEventListener("change", function (e) {
checkOther(e.target, s1);
});
}
<input type="checkbox" name="status_1" checked="checked" /> 1<br />
<input type="checkbox" name="status_2" checked="checked" /> 2
if (!$("#checkbox1").is(":checked") && !$("#checkbox2").is(":checked")) {
// both of them are unchecked u can eather check one or drop error
}
you can initiate it on change of element so.
$("#checkbox1").change(function() {
if(this.checked) {
//Do stuff
}
});
so in theory, you could create a function that checks if both unchecked and complete it with callback.
I have radio buttons like this -
<input type="radio" class="radiofilter" name="btype" id="btype1" checked='checked' autocomplete="off"><label for="btype1">All</label>
<input type="radio" class="radiofilter" name="btype" id="btype2" autocomplete="off"><label for="btype2">Option 1</label>
<input type="radio" class="radiofilter" name="btype" id="btype3" autocomplete="off" ><label for="btype3">Option 2</label>
I have an event listener which fires a script once the radio button selection is changed -
$('input.radiofilter:radio').change(
function(){
if($('#btype1').is(':checked')) {
z=1;
} else if($('#btype2').is(':checked')) {
z=2;
} else if($('#btype3').is(':checked')) {
z=3;
}
process(z);
});
Function process() takes a couple of seconds to process and the selection of radio button changes once the process is finished (after couple of seconds) leaving the user in doubt if the click on radio button has changed anything or not.
What I want to do is show a spinner overlay as soon as user clicks and hide the overlay once the process is finished
I thought this should be easy and did the following -
$('input.radiofilter:radio').change(
function(){
if($('#btype1').is(':checked')) {
z=1;
} else if($('#btype2').is(':checked')) {
z=2;
} else if($('#btype3').is(':checked')) {
z=3;
}
$(".radiofilter").attr('disabled',true);
$("#loader").show();
process(z);
$("#loader").hide();
$(".radiofilter").attr('disabled',false);
});
adding .show() and .hide() before and after calling process()
But it doesn't work for some reason I can't understand. What is the best way to do this?
Try using the "click" event, and you could do simpler:
jQuery('input.radiofilter').on('click', function(){
if(jQuery(this).is(':checked')){
z = jQuery(this).prop('id').replace('btype',''); // if doesnt work try just changing prop to attr (it depends on the jQuery version you are using)
}
$("#loader").show();
process(z);
// this one have to be added on the end of the proccess function as a callback$("#loader").hide();
});
Hope that can help you, if need more help with this code just ask or send a message.
I'm trying to make a "Manual Override" button that will allow a user to fill in forms of a field manually without auto-complete or the browser doing the math for them. I wanted to have a button that, if left on "No", would run JS but if not would alert them and not run the JS code. Any help in understanding how I'm going about this wrong would be greatly appreciated! Thank you so much!
HTML:
Manual Overide:
<label>No<input type="radio" name="manualOverride"
id="manualOverrideNo" value="no" checked /></label>
<label>Yes<input type="radio" name="manualOverride"
id="manualOverrideYes" value="yes" /></label>
JS:
//Manual Override Switch
$(document).ready(function() {
if($('#manualOverrideNo').prop('checked')) {
//Code For Auto-complete
} else {
alert("You have turned off Auto-complete");
}
});
The way you've laid this out, your if statement is going to fire right away on page load, which is probably not what you want - instead, you probably need to track the current setting in some way and behave appropriately, so the user can change things at run time.
Here's one approach:
$(document).ready(function() {
// var to hold state
var isManual = false;
// listener to update state
$('input[name="manualOverride"]').click(function() {
isManual = $(this).val() === 'yes';
});
// now, in your handlers for the input
$('#userInput').focus(function() {
if (isManual) {
// let the user do things manually
} else {
// do automatic stuff
}
})
});
See a fiddle: http://jsfiddle.net/4Ff8w/1/
Your code works fine in a JSFIDDLE: http://jsfiddle.net/9Aknj/
I'm not sure of your whole page context, but instead of having this code execute on DOM load, you may just need to locate at it in the proper location of the event handler that needs to process it.
Manual Overide set to NO:
<label>No<input type="radio" name="manualOverride"
id="manualOverrideNo" value="no" checked /></label>
<label>Yes<input type="radio" name="manualOverride"
id="manualOverrideYes" value="yes" /></label>
<br/><br/>
Manual Overide not set to NO:
<label>No<input type="radio" name="manualOverride2"
id="manualOverrideNo2" value="no" /></label>
<label>Yes<input type="radio" name="manualOverride2"
id="manualOverrideYes2" value="yes" checked /></label>
Javascript:
if($('#manualOverrideNo').prop('checked')) {
//Code For Auto-complete
alert("AUTOCOMPLETE CODE 1 DO HERE");
} else {
alert("You have turned off Auto-complete IN FIRST CASE");
}
if($('#manualOverrideNo2').prop('checked')) {
//Code For Auto-complete
alert("AUTOCOMPLETE CODE 2 DO HERE");
} else {
alert("You have turned off Auto-complete IN SECOND CASE");
}
Update: Based on you latest JSFIDDLE, I have fixed it to work: http://jsfiddle.net/LQW6g/7/
Basically, here is the javascript that attaches the KEYUP event handler and does the computation for you:
if($('#manualOverrideNo').prop('checked')) {
$('#footage').bind('keyup', function(){
var footage = parseFloat($(':input[name="footage"]').val(),10);
var total = '';
if(!isNaN(footage)){
total = Math.ceil(footage /7);
$(':input[name="postQuantity"]').val(total.toString());
} else {
$(':input[name="postQuantity"]').val("");
alert("You have input invalid number for footage.");
}
});
}
i've got a collection of 20 checkboxes like this here:
<div class="cbcell">
<input type="checkbox" class="checkbox" id="home_swimming_pool" name="Basen" value="35"> Basen
</div>
<div class="cbcell">
<input type="checkbox" class="checkbox" id="home_sauna" name="Sauna" value="45"> Sauna
</div>
with the following code i am saving and removing the checkbox state in the local storage which works very fine, also the filter function of dataTables works fine.
<script type="text/javascript" >
$(':checkbox').click(function(){
var name = $(this).attr('name');
var value = $(this).val();
if($(this).is(':checked')){
console.log( name, value ); // <- debug
oTable.fnFilter(name, value,false,true,false,true);
localStorage.setItem(this.name,'checked');
} else {
console.log( name, value ); // <- debug
oTable.fnFilter('',value,false,true,false,true);
localStorage.removeItem(this.name);
}
//})
});
</script>
Please tell me how to retrieve the state of each checkbox after a page reload. I tried it already with several functions and my last stand is:
$(document).ready(function() {
if (localStorage.getItem(this.value) == 'checked'){
$(this).attr("checked",true)
}
})
any help is highly appreciated.
Try this
$(':checkbox').each(function() {
$(this).prop('checked',localStorage.getItem(this.name) == 'checked');
});
In $(document).ready() function, this refers to the document, not to a checkbox, like in the $(':checkbox').click(). Plus if you think about it, you really need a way to iterate through your checkboxes. This is where .each() comes in. Inside the $(':checkbox').each() function, this will refer to a specific checkbox
Also it would be a good idea to check that localStorage is actually supported by the browser the code is running on, otherwise you will be getting errors.
a simple way is to wrap everything in an if (window.localStorage) { /* code here */}
Improved version
if (window.localStorage) {
$('.cbcell').on('click',':checkbox',function(){
var name = this.name;
var value = this.value;
if($(this).is(':checked')){
oTable.fnFilter(name, value,false,true,false,true);
//shorthand to check that localStorage exists
localStorage && localStorage.setItem(this.name,'checked');
} else {
oTable.fnFilter('',value,false,true,false,true);
//shorthand to check that localStorage exists
localStorage && localStorage.removeItem(this.name);
}
});
$(document).ready(function () {
$(':checkbox').each(function() {
$(this).prop('checked',localStorage.getItem(this.name) == 'checked');
});
});
}
Finally may I suggest spending some time going through the excellent Try jQuery tutorial at http://try.jquery.com/
I have a radio input group. If a radio is checked and I click again it becomes unchecked.
Is there a way to get the previous status of the radio onClick event?
<input name="options" type="radio" onClick="resetMeIfChecked()">
<input name="options" type="radio" onClick="resetMeIfChecked()">
<input name="options" type="radio" onClick="resetMeIfChecked()">
jQuery edition
// bind to retrieve old status
$('input[type="radio"]').mousedown(function() {
// if it was checked before
if(this.checked) {
// bind event to reset state after click is completed
$(this).mouseup(function() {
// bind param, because "this" will point somewhere else in setTimeout
var radio = this;
// apparently if you do it immediatelly, it will be overriden, hence wait a tiny bit
setTimeout(function() {
radio.checked = false;
}, 5);
// don't handle mouseup anymore unless bound again
$(this).unbind('mouseup');
});
}
});
But again, this is not how radio buttons are intended to be used. I think you'd be better of with a set checkbox'es where you could uncheck all other checkboxes than the current clicked (hence always max 1 selected)
A working example
I use this. You simply store the pre-click value and ! it into the value.
<input type=radio name="myoptions" value="1"
onmousedown="this.tag = this.checked;" onclick="this.checked = !this.tag;">
This behavior is not the expected one for radio buttons and I don't recommend it at all. Try to find another way of achieving this. Use another widget or another option to reset the field value:
http://jsfiddle.net/marcosfromero/rRTE8/
try this:
function resetMeIfChecked(radio){
if(radio.checked && radio.value == window.lastrv){
$(radio).removeAttr('checked');
window.lastrv = 0;
}
else
window.lastrv = radio.value;
}
<input value="1" name="options" checked="checked" type="radio" onClick="resetMeIfChecked(this)" />A
<input value="2" name="options" type="radio" onClick="resetMeIfChecked(this)" />B
<input value="3" name="options" type="radio" onClick="resetMeIfChecked(this)" />C
Its quite simple. Just follow the simple example and
var rdblength=document.formname.elementname.length;
alert('length='+rdblength);
for(i=0;i<rdblength;i++){
document.formname.elementname[i].checked=false;
}
Just find the length and make every index checked=true/false.
Ping me at:-
http://manojbardhan2009.blogspot.com
I had the same problem and figured it out. None of the answers above work exactly as I wanted - most of them require an additional button to reset the radio. The goal was to uncheck radio by clicking on the radio itself.
Here's the fiddle: http://jsfiddle.net/MEk5Q/1/
The problem was very complicated because the radio button value changes BEFORE the click event fires so when we're listening to the event we can't tell if the radio button was already checked or not. In both cases it is already checked.
Another approach was to listen to mousedown event. Unlike click, it fires before changing radio checked attribute but unchecking it inside event handler gives us nothing since it is checked back again during mouseup event.
My answer is a little ugly workaround so I generally don't suggest it to others and I'll probably abandon it myself. It works but it involves 20ms timeout function which I'm not fond of in cases like this.
Here is the code explanation:
$('input[type="radio"]').on('mousedown', function() {
if (this.checked) { //on mousedown we can easily determine if the radio is already checked
this.dataset.check = '1'; //if so, we set a custom attribute (in DOM it would be data-check="1")
}
}).on('mouseup', function() {
if (this.dataset.check) { //then on mouseup we determine if the radio was just meant to be unchecked
var radio = this;
setTimeout(function() {radio.checked = false;}, 20); //we give it a 20ms delay because radio checking fires right after mouseup event
delete this.dataset.check; //get rid of our custom attribute
}
});
As a timeout function I could use a string (less writing) but as far as I know it would be eval'ed. Though I don't trust eval function, I prefered anonymous function.
One more thing - one could ask why spreading the code into two separate event handlers while we can fire the timeout function on mousedown? Well, what if someone press the mouse on a radio and holds it for a few secs or even someone is simply a very slow person ;). Generally, with this solution we omit the problem of lag between mousedown and mouseup.
If you need some more info about dataset, here's the MDN reference:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.dataset
This property came with HTML5 and might be not cross-browser, I guess, so if you want 100% compatibility, replace it with any other solution that'll contain the data, you name it.
Sorry about jQuery here and there but I hope you're fine with it - it was much easier that way.
Hope you'll enjoy it.
$('input[type="radio"]').on("mousedown", function () {
if (this.checked) {
$(this).one("click", function () {
this.checked = false;
});
}
});
I was never too happy about being forced to aim at that tiny radio button, so I came up with a larger target AND a way to turn a radio group off without resorting to anything that would upset the HTML / JavaScript purists.
The technique relies on not molesting the radio buttons at all via event handlers, but checking for a readonly proxy for each one instead. Everything is contained in what's below in pure JavaScript using a radio group to select a type of cheese, or no cheese at all.
I purposely used no styling in this example to avoid that added layer. The dump button will tell you what the three checked states are, so use it to interrogate what happened after hitting the radio or text input elements. For example simplicity I used a global to remember the former state, but a more elegant method is to use a dataset, which I what I use in the real code of my application.
<!DOCTYPE html>
<html>
<head>
<title>Uncheck a radio button</title>
<script>
function attachEventListener(target, eventType, functionRef, capture) {
"use strict";
if (typeof target.addEventListener !== 'undefined') {
// Most modern browsers
target.addEventListener(eventType, functionRef, capture);
} else if (typeof target.attachEvent !== 'undefined') {
// IE
target.attachEvent('on' + eventType, functionRef);
} else {
eventType = 'on' + eventType;
if (typeof target[eventType] === 'function') {
var oldListener = target[eventType];
target[eventType] = function() {
oldListener();
return functionRef();
};
} else {
target[eventType] = functionRef;
}
}
}
</script>
</head>
<body>
<form>
<input id="Cheddar-radio" class="radio" type="radio" name="Cheeses-0" value="Cheddar Cheese" tabindex="-1"></input>
<input id="Cheddar-text" type="text" readonly value="Cheddar Cheese" tabindex="-1"></input><br>
<input id="Swiss-radio" class="radio" type="radio" name="Cheeses-0" value="Swiss Cheese" tabindex="-1"></input>
<input id="Swiss-text" type="text" readonly value="Swiss Cheese" tabindex="-1"></input><br>
<input id="American-radio" class="radio" type="radio" name="Cheeses-0" value="American Cheese" tabindex="-1"></input>
<input id="American-text" type="text" readonly value="American Cheese" tabindex="-1"></input><br><br>
<input onclick="dumpStates()" type="button" name="button" value="dump" tabindex="-1"></input>
</form>
<script>
window.onload = addRadioListeners;
function addRadioListeners() { // But do it on the -text elements.
attachEventListener(document.getElementById('Cheddar-text') , 'mousedown', rememberCurrentState, false);
attachEventListener(document.getElementById('Swiss-text') , 'mousedown', rememberCurrentState, false);
attachEventListener(document.getElementById('American-text'), 'mousedown', rememberCurrentState, false);
attachEventListener(document.getElementById('Cheddar-text') , 'mouseup', checkNewState, false);
attachEventListener(document.getElementById('Swiss-text') , 'mouseup', checkNewState, false);
attachEventListener(document.getElementById('American-text'), 'mouseup', checkNewState, false);
}
function dumpStates() {
console.log(document.getElementById('Cheddar-radio').checked +
' ' + document.getElementById('Swiss-radio').checked +
' ' + document.getElementById('American-radio').checked);
}
var elementWasChecked; // Global - Could just as well use a dataset attribute
// on either the -radio or -text element and check it instead.
function rememberCurrentState(event) {
var element;
var radioElement;
element = event.target;
radioElement = document.getElementById(element.id.replace(/text/,'radio'));
elementWasChecked = radioElement.checked;
radioElement.checked = true;
}
function checkNewState(event) {
var element;
var radioElement;
element = event.target;
radioElement = document.getElementById(element.id.replace(/text/,'radio'));
var currentState = radioElement.checked;
if (elementWasChecked === true && currentState === true) {
console.log('Changing ' + radioElement.id + ' to false.');
radioElement.checked = false;
}
};
</script>
</body>
</html>
If you click on the radio buttons they work as expected. If you click on the text items next to each, they are a proxy for the radio buttons with one exception. If you click on a text item that has an associated radio button that's already checked, it will uncheck it. Therefore, the text proxy's are event triggered, and not the radio buttons.
The added benefit is that you can now hit the larger text target too.
If you want to make it simple and wouldn't mind using a double-click event try something like this:
<input name="options" type="radio" ondblclick="this.checked=false;">
#jerjer's answer is almost perfect, but radios can be switched also by arrows if the radio group has the focus (so mousedown event is not enough). Alas, the radio group also gets checked when activated by focus shift (Tab), which can undesirably check one option. Therefore space should uncheck the focused radio, just like the checkbox behavior.
This code fixes that for all radios (Most credit still goes to jerjer):
window.addEventListener("DOMContentLoaded", function() {
var radios = document.querySelectorAll("input[type=radio]");
for(var i=0; i<radios.length; ++i) {
radios[i].addEventListener("click", function(e) {
if(e.target.checked && e.target.value == window.lastrv){
e.target.checked = false;
window.lastrv = 0;
}
else
window.lastrv = e.target.value;
});
radios[i].addEventListener("keypress", function(e) {
if(e.keyCode==32) e.target.click();
});
}
});