I created a toggle switch checkbox and aplied the logic below:
1] If user clicks on toggle switch class="os_section-slider" the script will check if the input containing element's name is checked.
1-A] If the element is checked then change it to UNchecked and add that element into array named os_tagsToRemove
1-B] If the element is UNchecked then change it to checked and add that element into array named os_tagsToAdd
HTML
<span class="os_section-name">first</span>
<input type="checkbox" class="os_section-check" id="first" checked="checked">
<label class="os_section-slider" for="first"></label>
<div class="line-space-between"></div>
<span class="os_section-name">second</span>
<input type="checkbox" class="os_section-check" id="second">
<label class="os_section-slider" for="second"></label>
JS
$(".os_section-slider").click(function() {
if($(this).prev().is(":checked")) { //if checked
$(this).prev().attr("checked", false);
var os_tagName = $(this).prev().attr("id").toString();
os_tagsToRemove.push(os_tagName);
os_tagsToAdd.splice($.inArray(os_tagName, os_tagsToAdd),1);
} else { //if unchecked
$(this).prev().attr("checked", true);
var os_tagName = $(this).prev().attr("id").toString();
os_tagsToAdd.push(os_tagName);
os_tagsToRemove.splice($.inArray(os_tagName, os_tagsToRemove),1);
}
});
My problem is, when my page reloads and my toggle switch appears in a modal box and I try to click on the switcher button I have to click 2 times until the checked attribute is added/removed.
The first click always only pushes the value into the array or removes it from the array but doesn't apply $(this).prev().attr("checked", true); nor $(this).prev().attr("checked", false);.
But after the second click on each switcher button, everything from that moment works fine.
Add this to load your add/remove arrays:
// Onload remove array fill
$("[type='checkbox']").each(function(){
if( $(this).is(":checked") ){
os_tagsToRemove.push($(this).attr("id"));
}else{
os_tagsToAdd.push($(this).attr("id"));
}
});
Then, your logic was all reversed.
First, when you click on the label, which is defined as for="anID", the checked state of the coresponding checkbox already changes. You do not have to script that.
Then, when you look if it is checked, you have to know that this verification is made AFTER the checkbox state has changed. So I reversed your if conditions.
var os_tagsToAdd = [];
var os_tagsToRemove = [];
$(".os_section-slider").click(function() {
console.clear();
var os_tagName = $(this).prev().attr("id");
//if checked AFTER the click
if($(this).prev().is(":checked")) {
if($.inArray(os_tagName, os_tagsToAdd) == -1){
os_tagsToAdd.push(os_tagName);
}
os_tagsToRemove.splice($.inArray(os_tagName, os_tagsToRemove),1);
//if unchecked AFTER the click
} else {
if($.inArray(os_tagName, os_tagsToRemove) == -1){
os_tagsToRemove.push(os_tagName);
}
os_tagsToAdd.splice($.inArray(os_tagName, os_tagsToAdd),1);
}
console.log( os_tagsToAdd );
console.log( os_tagsToRemove );
});
// Onload remove array fill
$("[type='checkbox']").each(function(){
if( $(this).is(":checked") ){
os_tagsToRemove.push($(this).attr("id"));
}else{
os_tagsToAdd.push($(this).attr("id"));
}
});
console.log( os_tagsToAdd );
console.log( os_tagsToRemove );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="os_section-name">first</span>
<input type="checkbox" class="os_section-check" id="first" checked="checked">
<label class="os_section-slider" for="first">Label</label>
<div class="line-space-between"></div>
<span class="os_section-name">second</span>
<input type="checkbox" class="os_section-check" id="second">
<label class="os_section-slider" for="second">Label</label>
Related
So I have a donation form and people can select different amounts to donate, so I want to automatically check a checkbox if the donation amount is bigger or equal than 20.
This the html (the data total stays the same the text is the element that change)
<span class="give-final-total-amount" data-total="20.00">$455.00</span>
<input type="checkbox" value="2" name="group[12581][2]" id="mce-group[12581]-12581-1">
This what I'm trying with jQuery
$( document ).ready(function() {
if ($(".give-final-total-amount").text() >= 20.00) {
jQuery("#mce-group[12581]-12581-1").prop("checked", true);
}
else {
$("#mce-group[12581]-12581-1").prop("checked", false);
}
});
The dollar sign is preventing your comparison from working. See additional comments below:
$(function() {
// Get a reference to the checkbox
var chk = document.getElementById("mce-group[12581]-12581-1");
// You can't compare the value of the span against a number if the value is not-numeric
// you have to remove the dollar sign first
if ($(".give-final-total-amount").text().replace("$", "") >= 20) {
// No need for JQuery on this, just set the checked property to true
chk.checked = true;
} else {
// Set checked property to false
chk.checked = false;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="give-final-total-amount" data-total="20.00">$455.00</span>
<input type="checkbox" value="2" name="group[12581][2]" id="mce-group[12581]-12581-1">
I have a group of checkboxes that when you click ONE, they should ALL be checked.
When a user clicks one checkbox, it checks all the other checkboxes starting with that class name. What I want is for the user to click a checkbox, and $(".atpSelections").change is triggered only once per click.
Here's the code:
$(".atpSelections").change(function() {
console.log("CHANGED");
//Check ALL other checkboxes starting with that class name:
var className = $(this).attr("class");
className=className.replace("atpSelections ", "");
className=className.trim();
className=className.split("-");
//Get current checkbox state
var currentState = $(this).attr("checked");
//Now loop through all other checkboxes starting
//with the same class name and check them:
$("input[class*='"+className[0]+"-']").each(function(i){
//THIS IS TRIGGERING "$(".atpSelections").change"!!
if(currentState && currentState=="checked")
{
$(this).prop('checked', true);
}else
{
$(this).prop('checked', false);
}
});
});
The Problem
The problem is that when the user clicks one checkbox, the $(".atpSelections").change method gets triggered over and over because $(this).prop('checked', true); triggers $(".atpSelections").change again, and it just goes round and round.
So 1 click to a checkbox triggers 100s "change" events, when I only want it triggered once.
How do I alter the checkbox's state inside $(".atpSelections").change without triggering $(".atpSelections").change again?
Attempts
I tried changing $(".atpSelections").change to $(".atpSelections").click but it had the same issue. I think $(this).prop('checked', true); triggers the click event.
Solution
I used #James 's answer and changed
var currentState = $(this).attr("checked");
to
var currentState = $(this).prop("checked") ? "checked" : "";
and it worked perfectly! Thanks.
Here's the JSFiddle: https://jsfiddle.net/zL7amo0y/
The problem is with your currentState variable. Please do a console.log on it. I'm guessing it's undefined?
Below is your code fixed in both jQuery and Vanialla JS.
JQuery:
$(".atpSelections").change(function() {
var currentState = $(this).prop("checked");
console.log(currentState);
$("input[name='checkboxToCheck']").each(function(i){
if(currentState)
{
$(this).prop('checked', true);
}else
{
$(this).prop('checked', false);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form name="myForm">
<label for="checkbox1">Main Checkbox:</label>
<input class="atpSelections" value="checkbox1" type="checkbox" id="checkbox1" />
<label for="checkbox2">Checkbox2:</label>
<input name="checkboxToCheck" value="checkbox1" type="checkbox" id="checkbox1" />
<label for="checkbox3">Checkbox3:</label>
<input name="checkboxToCheck" value="checkbox1" type="checkbox" id="checkbox1" />
</form>
Vanilla JS:
var checkbox = document.getElementById("checkbox1")
var checkboxToCheck = document.getElementsByName("checkboxToCheck");
checkboxToCheck = [].slice.call(checkboxToCheck);
function checkAllBoxes() {
checkboxToCheck.forEach((element) => {
if (checkbox.checked) {
element.checked = true;
} else {
element.checked = false;
}
});
}
checkbox.addEventListener("change", checkAllBoxes);
<form name="myForm">
<label for="checkbox1">Main Checkbox:</label>
<input value="checkbox1" type="checkbox" id="checkbox1" />
<label for="checkbox2">Checkbox2:</label>
<input name="checkboxToCheck" value="checkbox1" type="checkbox" id="checkbox1" />
<label for="checkbox3">Checkbox3:</label>
<input name="checkboxToCheck" value="checkbox1" type="checkbox" id="checkbox1" />
</form>
I'm thinking know what is your problem, I got it with a plugin of checkboxes too.
Try this
$(".atpSelections").on('change.custom', function(e) {
console.log("CHANGED CUSTOM");
//Check ALL other checkboxes starting with that class name:
var className = $(this).attr("class");
className=className.replace("atpSelections ", "");
className=className.trim();
className=className.split("-");
//Get current checkbox state
var currentState = $(this).attr("checked");
//Now loop through all other checkboxes starting
//with the same class name and check them:
$("input[class*='"+className[0]+"-']")
.off('change.custom')
.each(function(i){
//THIS IS TRIGGERING "$(".atpSelections").change"!!
if(currentState && currentState=="checked"){
$(this).prop('checked', true);
}else{
$(this).prop('checked', false);
}
});
});
Normally it's okay :)
I have a table with three columns and multiple rows. 2nd and third column consist of a textbox(first child of a container) and a checkbox respectively.
Textbox
<td class="SBS1 c4">
<input class="Medium InputText" type="text" name="QR~QID33#1~1~1~TEXT" id="QR~QID33#1~1~1~TEXT" value="" disabled="">
<label class="offScreen" for="QR~QID33#1~1~1~TEXT"> - - hh</label>
</td>
Checkbox
<td class="SBS2 c7">
<input type="checkbox" id="QR~QID33#2~1~1" name="QR~QID33#2~1~1" value="Selected">
<label class="q-checkbox q-checked" for="QR~QID33#2~1~1"></label>
<label class="offScreen" for="QR~QID33#2~1~1"> - ó †ºrandom text</label>
</td>
I have to disable and enable the textboxes in each row on checkbox check and uncheck respectively using javascript. but there seem to be some pagelifecycle issues with the script I am using. Here is the Javascript that I am using in my Qualtrics survey JS interface,
Qualtrics.SurveyEngine.addOnload(function()
{
/*Place Your JavaScript Here*/
var count=document.getElementsByClassName("q-checkbox").length;
for(var i=0;i<count;i++)
{
document.getElementsByClassName("q-checkbox")[i].parentNode.addEventListener("click",hideFunc);
}
function hideFunc()
{
console.log(this.className);
if(this.classList.contains("checkers"))
{
//this.classList.toggle("checkers");
this.previousSibling.previousSibling.previousSibling.firstChild.disabled="false";
this.classList.add("checkers");
return;
}
else
if(!(this.classList.contains("checkers")))
{
this.previousSibling.previousSibling.previousSibling.firstChild.disabled="true";
this.classList.remove("checkers");
return;
}
}
});
I am just trying to toggle or add/remove the class "checkers"and setting "disabled" property of the texboxes accordingly. The code above in HideFunc is one of the work-around I have tried but it is not working.
Is there another way to check for checkbox change?
As the first comment hinted, a better approach is to check the status of the checkbox rather than add/remove a class. Also, making use of prototypejs makes it easier. Try this:
Qualtrics.SurveyEngine.addOnload(function() {
var qid = this.questionId;
$(qid).select('tr.Choice').each(function(choice,idx) { //loop through each row
var cbox = choice.select('td.SBS2').first().down(); //cbox enables 1st question in row
var txtEl = choice.select('td.SBS1').first().down(); //text input to be enabled/disabled
if(cbox.checked == false) { //initialize text input disabled status
txtEl.value = null; //blank text input
txtEl.disabled = true; //disable text input
}
cbox.on('click', function(event, element) { //enable/disable text input on cbox click
if(cbox.checked == false) { //unchecked
txtEl.value = null; //blank text input
txtEl.disabled = true; //disable text input
}
else { //checked
txtEl.disabled = false; //enable text input
}
}); //end on function
}); //end row loop
});
This is another solution I could come up with ,apart from the correct solution by T. Gibbons
var $j= jQuery.noConflict();
$j("td.SBS2 ").click(function(){
$j(this).closest("tr").find(".InputText").prop("disabled",$j(this).children("input")[0].checked);
$j(this).closest("tr").find(".InputText").prop("value","");
var len=document.getElementsByClassName("InputText").length;
for(var i=0;i<=len;i++)
{
document.getElementsByClassName("InputText")[i].style.width="300px";
}
});
I've got the following jQuery script correctly displaying and checking two hidden checkboxes. The only problem is that I'm trying to hide both of these checkboxes but when I uncheck my visible checkbox they remain checked?
<input type="checkbox" name="JobType[]" class="visiChk" id="nineteen" value="19" <?php echo (isset($_GET["JobType"]) && !empty($_GET["JobType"]) && in_array("19", $_GET["JobType"])) ? "checked": ""; ?> /> Plumbing
<label id="hiddenLabel" style="display:none">
<input type="checkbox" name="JobType[]" class="visiChk" id="seventeen" value="17" <?php echo (isset($_GET["JobType"]) && !empty($_GET["JobType"]) && in_array("17", $_GET["JobType"])) ? "checked": ""; ?> /> Plumbing
<input type="checkbox" name="JobType[]" class="visiChk" id="eighteen" value="18" <?php echo (isset($_GET["JobType"]) && !empty($_GET["JobType"]) && in_array("18", $_GET["JobType"])) ? "checked": ""; ?> /> Plumbing
</label>
<script>
// update if any are checked/unchecked
$('.visiChk').change(function() {
var hiddenLabel = $('#hiddenLabel')[0];
var seventeen = $('#seventeen')[0];
var eighteen = $('#eighteen')[0];
// Are any of them checked ?
if ($('.visiChk:checked').length > 0) {
hiddenLabel.style.display = 'block';
seventeen.checked = true;
eighteen.checked = true;
} else {
hiddenLabel.style.display = 'none';
seventeen.checked = false;
eighteen.checked = false;
}
});</script>
There's a logical error occurring here that might not be readily obvious with the hidden fields. When you are checking to see if any of the checkboxes are marked, you're checking all of them, even the hidden ones.
So, walk through the cycle once more. The page loads, no checkboxes have been checked. A user checks the visible one. All three are checked. The user then unchecks only the visible one. Your logic check here
if ($('.visiChk:checked').length > 0) {
is looking at all three of them. Are there any checked? Yes, the two hidden ones still are! So, all three will be set to checked again. You'll need a way to only look at the visible checkbox and then update the invisible ones accordingly. A unique ID or different class would work well.
I wrote up an example jsfiddle that helps to illustrate what's going on. Instead of hiding the checkboxes, I set the font color to grey to show which ones should actually be hidden.
https://jsfiddle.net/sm1215/d9geaog4/1/
Edit: Also, I set up a console log to show the result of the logic check going on. When the page first loads (no checkboxes are checked) and the user checks one, it evaluates to 1. Uncheck the visible one, and it evaluates to 2 - showing the 2 hidden checkboxes are still being counted.
Edit 2: Here's the code from the jsfiddle for reference in case the fiddle is ever lost.
HTML
<input type="checkbox" name="JobType[]" id="nineteen" class="visiChk" value="19" /> Plumbing
<label id="hiddenLabel" style="color:silver; /*display:none*/">
<input type="checkbox" name="JobType[]" class="visiChk" id="seventeen" value="17" /> Plumbing
<input type="checkbox" name="JobType[]" class="visiChk" id="eighteen" value="18" /> Plumbing
</label>
JS
// update if any are checked/unchecked
$('.visiChk').change(function() {
var hiddenLabel = $('#hiddenLabel')[0];
var seventeen = $('#seventeen')[0];
var eighteen = $('#eighteen')[0];
// Are any of them checked ?
console.log($('#nineteen:checked').length);
if ($('#nineteen:checked').length > 0) {
hiddenLabel.style.display = 'block';
seventeen.checked = true;
eighteen.checked = true;
} else {
// Commenting this out so the hidden fields stay visible for demo purposes
//hiddenLabel.style.display = 'none';
seventeen.checked = false;
eighteen.checked = false;
}
});
I am using the bootstrap switches to change a check box into a toggle box. When the page loads the switch is in the data-off position being red and text saying no.
<div class="make-switch" id="use_map_switch" data-on-label="Yes" data-off-label="No" data-on="success" data-off="danger">
<input type="checkbox" name="use_map" id="use_map" value="1" {if $form_data.use_map eq 1}checked{/if} />
</div>
I run a jQuery script once the check/switch is clicked and changed to yes/green. If the results turn back false I want to change the switch/check back to No/red.
I have tried using the line $('#use_map').prop('checked', false); but this has had no affect.
$('#use_map_switch label').click(function(){
// need to do opposite
// if its checked when clicked then switch will be going to unchecked
if($('#use_map').is(':checked')){
$('.map-area').hide();
} else {
address = getAddress();
if(address == ''){
modalTitle = 'Error';
modalText = 'Please enter an address before using the map';
$('#use_map').prop('checked', false);
show_modal(modalTitle, modalText);
} else {
$('.map-area').show();
$('.map-area').html(address);
}
}
});