Checkbox Functionality with Two Series of Checkboxes - javascript

I'm currently developing a form that has two containers with checkboxes. There first is the master and then there's the secondary which corresponds to the master.
The first container's checkboxes contain a data attribute value such as: "One", "Two", "Three", etc.
Upon clicking one of the master checkboxes (the onCheck function) it checks all the input data attribute values that have an input of "checked", and then proceeds to check every checkbox in the secondary container (which has an array of information in its data attribute) and if there's a match between any of the information, they get checked.
What I'm trying to figure out is the uncheck functionality (the offCheck function). When the user unchecks a master checkbox, it should look through each master input checkbox and if there's one that's checked and it corresponds to the data information in one of the secondary checkboxes, it shouldn't be unchecked. If there's no corresponding information, it gets unchecked.
Please let me know if you need clarification as this can be a bit confusing.
HTML:
<div class="master">
<input type="checkbox"
data-information="One"
/> Primary Checkbox One
<input type="checkbox"
data-information="Two"
/> Primary Checkbox Two
<input type="checkbox"
data-information="Three"
/> Primary Checkbox Three
</div>
<div class="secondary">
<input type="checkbox"
data-information='["One", "Seven", "Ten"]'
/> Secondary Checkbox One
<input type="checkbox"
data-information='["Two", "Three", "Ten"]'
/> Secondary Checkbox One
</div>
jQuery / JavaScript:
function onCheck(){
// Gather all information from checkboxes that are checked
var informationOne = [];
$(".master input:checkbox").each(function(){
if($(this).is(":checked")){
informationOne.push($(this).data("information"));
}
});
$('.secondary input:checkbox').each(function(){
var informationTwo = [];
informationTwo = $(this).data("information");
for(var i=0; i<informationTwo.length; i++){
if($.inArray(informationTwo[i], informationOne) != -1){
$(this).prop("checked", true);
}
}
});
}
function offCheck(){
}
$(".master input:checkbox").change("checked", function(){
if($(this).is(":checked")){
onCheck();
} else {
offCheck();
}
});

Welcome to StackOverflow, Nate!
I took a slightly different approach. Instead of asking, "what changed, and how does it affect the checkboxes?" this code says "something changed, set all the checkboxes according to the current state."
function setCheckboxes(){
[...document.querySelectorAll('.secondary input[type=checkbox]')].forEach((i) => {
i.checked = shouldBeChecked(i);
});
}
function shouldBeChecked(el) {
const matchingNumbers = JSON.parse(el.dataset.information);
return [...document.querySelectorAll('.master input[type=checkbox]:checked')].some((i) =>
matchingNumbers.includes($(i).data('information'))
);
}
$(".master input:checkbox").change("checked", function(){
setCheckboxes();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="master">
<input type="checkbox"
data-information="One"
/> Primary Checkbox One
<input type="checkbox"
data-information="Two"
/> Primary Checkbox Two
<input type="checkbox"
data-information="Three"
/> Primary Checkbox Three
</div>
<div class="secondary">
<input type="checkbox"
data-information='["One", "Seven", "Ten"]'
/> Secondary Checkbox One
<input type="checkbox"
data-information='["Two", "Three", "Ten"]'
/> Secondary Checkbox One
</div>

Related

How does select all checkbox work correctly?

I have to implement a functionality where I have few radio buttons, when I click on a radio button I'll get check boxes, out of which the first check box is "Select all". Rest of the check boxes are few options. When I click on any of these check boxes, a 5-star rating with label as the check box name should come up.
For example (I'm sorry that I can't post a UI picture of this) :
radiobutton1 radiobutton2
when I click on radiobutton1
select_all check box
abc check box
pqr check box
xyz check box
These check boxes will show up.
Now, If I select pqr check box, 5-star rating with a label of "pqr" will come.
pqr
star1 star2 star3 star4 star5
Now, If I select both pqr check box and xyz check box, I'll get their respective ratings :
pqr
star1 star2 star3 star4 star5
xyz
star1 star2 star3 star4 star5
If I select, "Select all" check box, then all the check boxes under it gets checked and ratings for the same will come :
abc
star1 star2 star3 star4 star5
pqr
star1 star2 star3 star4 star5
xyz
star1 star2 star3 star4 star5
I wrote code for rating, radio buttons, check boxes, everything. But I'm getting issue for "select all" checkbox. (My code has lot of other variables and it's sort of big, because this functionality is just a part of a page, so I'm not posting my code here). Also, please note that these options(abc, pqr, xyz) are dynamic and are coming from backend.
<div class="db-checkbox skills_options select_all hidden"><input type="checkbox" id="sa" onClick="toggle(this)"><label for="sa">Select all skills</label></div>
<div class="db-checkbox skills_options for_rating hidden"><input class = "skills_select" type="checkbox" value="abc" name="abc" id="a"><label for="a">abc</label></div>
<div class="db-checkbox skills_options for_rating hidden"><input class = "skills_select" type="checkbox" value="pqr" name="pqr" id="p"><label for="p">pqr</label></div>
<div class="db-checkbox skills_options for_rating hidden"><input class = "skills_select" type="checkbox" value="xyz" name="xyz" id="x"><label for="x">xyz</label></div>
This is the code for the check boxes and the toggle function in select all check box is as follows :
function toggle(source) {
checkboxes = document.getElementsByClassName('skills_select');
for(var i=0, n=checkboxes.length;i<n;i++) {
checkboxes[i].checked = source.checked;
}
}
And I wrote two on click functions, one for the individual options (when I click on abc, pqr, xyz for the respective ratings to show up) and one for the select all options (when I click on select all, ratings of all options to show up). Also, notice here that for each radio button, there are check boxes of it's own.
Now, my issue is that, When I click on select all, all options are getting selected, when I deselect select all, all options are getting unchecked, but, when I select, select all check box, and then I uncheck any option under it, select all check box should also gets unchecked right? Such things are not happening and I can't figure out how I resolve this. Can you please tell me how do I make a select all check box work correctly that works fine in all the scenarios in javascript and jquery (when I select select all, and then uncheck abc, pqr and/or xyz; select all should get unchecked, when I select abc, pqr and xyz individually ratings for abc, pqr, xyz will come and now when I click on select all, again all shouldn't come (it's coming like this for me because i wrote two onclick functions right?); all such cases). Thank you!
"when I select, select all check box, and then I uncheck any option under it, select all check box should also gets unchecked right?"
Is the following what you were trying to do? Incidentally I removed the ID attributes as they were invalid and then moved the input within the label to associate the two.
let checker=document.getElementById('checker');
let col=document.querySelectorAll('input.skills_select');
checker.addEventListener('click',function(e){
col.forEach(n=>n.checked=this.checked);
});
col.forEach( n=>{
n.addEventListener('click',function(e){
if( !this.checked && checker.checked )checker.checked=false;
})
})
<div class='db-checkbox skills_options select_all hidden'>
<label><input type='checkbox' id='checker'>Select all skills</label>
</div>
<div class='db-checkbox skills_options for_rating hidden'>
<label><input class='skills_select' type='checkbox' value='abc' name='abc'>abc</label>
</div>
<div class='db-checkbox skills_options for_rating hidden'>
<label><input class='skills_select' type='checkbox' value='pqr' name='pqr' />pqr</label>
</div>
<div class='db-checkbox skills_options for_rating hidden'>
<label><input class='skills_select' type='checkbox' value='xyz' name='xyz' />xyz</label>
</div>
There are many ways to achieve the effect that you are looking for (Which is the beauty of coding). Abronsius answer is very elegant and simple. Jialis answer uses JQuery and includes a suggestion to handle raitings. I'll provide a thrid different approach.
First we divide the checkboxes into sections. This is simply a wrapper div around a group of checkboxes, where the first checkbox should always be the Select all option. We will also make use of the data attribute to separate what function a checkbox serves (Select all or just a single option).
We will then grab every single checkbox on the page and bind to their change event, handling all checkboxes in the same function. We will use data attribute to seperate them and the section div to group them.
This gives us a very modular approach where you can easily add as many sections, checkboxes and raitings as you'd like.
function showRaitingForCheckbox(checkbox) {
/* For you to implement... */
}
function hideRaitingForCheckbox(checkbox) {
/* For you to imeplement... */
}
/* We grab every single checkbox on this page and loop through them. */
let checkboxes = document.querySelectorAll("input[type=checkbox]")
checkboxes.forEach(function (element) {
/* Bind an event listener for the 'change'. */
element.addEventListener("change", function (e) {
let checkbox = e.target; // Checkbox that has been clicked
let type = checkbox.dataset.id; // It's 'type', all or 'single'
let parentNode = checkbox.parentNode; // Parent node, so that we can reach other checkboxes in this section
let children = parentNode.querySelectorAll("input[type=checkbox]"); // All checkboxes within this section
/* Seperate logic for clicking on 'Select all' and 'Select single option' */
if (type == "all") {
/* We clicked on the 'Select all' checkbox. Go through all checkboxes for this section. */
children.forEach(function (child) {
/* Make sure we're only targeting 'Select single option' checkboxes. */
if (child.dataset.id == "single") {
/* Either check or uncheck the checkbox, also toggle raitings. */
if (checkbox.checked == true) {
child.checked = true;
showRaitingForCheckbox(child)
} else {
child.checked = false;
hideRaitingForCheckbox(child);
}
}
});
} else if (type == "single") {
/* We clicked on a 'Select single option' checkbox, let's toggle raitings first. */
if (checkbox.checked == true)
showRaitingForCheckbox(checkbox);
else
hideRaitingForCheckbox(checkbox);
/* Calculate how many checkboxes have been selected in this section. */
let amountOfCheckedCheckboxes = 0;
for (let i = 0; i < children.length; i++) {
if (children[i].dataset.id == "single" && children[i].checked == true)
amountOfCheckedCheckboxes++;
}
/* If not all checkboxes are selected, unselect the 'Select all' box, otherwise select it. */
if (amountOfCheckedCheckboxes < children.length - 1)
children[0].checked = false;
else
children[0].checked = true;
}
});
});
<div class="section">
<input type="checkbox" data-id="all">Select all</input>
<input type="checkbox" data-id="single">Select single option</input>
<input type="checkbox" data-id="single">Select single option</input>
<input type="checkbox" data-id="single">Select single option</input>
<input type="checkbox" data-id="single">Select single option</input>
</div>
<div class="section">
<input type="checkbox" data-id="all">Select all</input>
<input type="checkbox" data-id="single">Select single option</input>
<input type="checkbox" data-id="single">Select single option</input>
<input type="checkbox" data-id="single">Select single option</input>
<input type="checkbox" data-id="single">Select single option</input>
</div>
<div class="section">
<input type="checkbox" data-id="all">Select all</input>
<input type="checkbox" data-id="single">Select single option</input>
<input type="checkbox" data-id="single">Select single option</input>
<input type="checkbox" data-id="single">Select single option</input>
<input type="checkbox" data-id="single">Select single option</input>
</div>
Funny side note: I don't think i've ever written the word checkbox this many times before.
I don't know how you want to add the rating part to DOM
But this code can probably help.
It is better to use the change event for checkboxes
$("#sa").on("change", function(){
if( $(this).is(":checked" ) )
{
$(".skills_select").each(function(){
if(!$(this).is(":checked" ))
{
$(this).prop('checked', true)
$(this).change()
}
})
} else
{
$(".skills_select").each(function(){
if($(this).is(":checked" ))
{
$(this).prop('checked', false)
$(this).change()
}
})
}
})
$(".skills_select").on("change", function(){
// Get parent div
let parent_div = $(this).closest('div');
// It's for example, it's better to use hidden attribute
if( $(this).is(":checked" ) )
$(parent_div).append("<div class='rate'> <br> star1 star2 ... </div>")
else
$(parent_div).find(".rate").remove()
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="db-checkbox skills_options select_all hidden"><input type="checkbox" id="sa" ><label for="sa">Select all skills</label></div>
<div class="db-checkbox skills_options for_rating hidden"><input class = "skills_select" type="checkbox" value="abc" name="abc" id="a"><label for="a">abc</label></div>
<div class="db-checkbox skills_options for_rating hidden"><input class = "skills_select" type="checkbox" value="pqr" name="pqr" id="p"><label for="p">pqr</label></div>
<div class="db-checkbox skills_options for_rating hidden"><input class = "skills_select" type="checkbox" value="xyz" name="xyz" id="x"><label for="x">xyz</label></div>

How to check if radiobutton is selected (javascript, html)

I am trying to check if a radio button is selected or not. If the "morn_before" radiobutton is selected, the data will be stored as "2", but if the "morn_after" radiobutton is selected instead, the data will be stored as "1".
Currently my code show below is not working. For example when i select the "morn_before" radiobutton, it doesnt print "morn_before checked true" in the console, despite me putting console.log("morn_before checked true") in that if statement.
HTML:
<div class="radiobutton">
<input type="radio" id="morn_before" name="morn_time" value="morn_before">
<label for="morn_before">Before Food</label><br>
<input type="radio" id="morn_after" name="morn_time" value="morn_after">
<label for="morn_after">After Food</label><br><br>
</div>
Javascript:
function check() {
let user=firebase.
auth().currentUser;
let uid;
if(user!=null){
uid=user.uid;
}
var firebaseRef = firebase.database().ref();
if(document.getElementById("morn_before").checked){
console.log("morn_before checked true");
firebase.database().ref(uid).child('/radiobutton/').child('/morn_time/').set("2");
}
else if(document.getElementById("morn_after").checked){
firebase.database().ref(uid).child('/radiobutton/').child('/morn_time/').set("1");
}
}
check();
You don't need any JavaScript for this. You can have a completely different display than the stored value.
<div class="radiobutton">
<input type="radio" id="morn_before" name="morn_time" value="2">
<label for="morn_before">Before Food</label><br>
<input type="radio" id="morn_after" name="morn_time" value="1">
<label for="morn_after">After Food</label><br><br>
</div>
Should produce the same result. The only improvement would be to set one of these to default true, in case the user chose neither. But that'd be up to you.
ADDITIONAL INFO: You are not supposed to read a radio button group that way.
You should go over some basics of HTML INPUT tag such as
https://www.geeksforgeeks.org/how-to-get-value-of-selected-radio-button-using-javascript/

Selected value of Radio Button doesn't change

In the view, I have these two radio buttons:
#Html.RadioButtonFor(c => c.CampaignType, "Exclusive")<label>Exclusive</label>
#Html.RadioButtonFor(c => c.CampaignType, "Shared")<label>Shared</label>
The value for Model.CampaignType is set in the controller before the page loads. All of this works fine. If Exclusive is what's saved in the DB, then we get this rendered in the HTML:
<input checked="checked" id="CampaignType" name="CampaignType" type="radio" value="Exclusive"><label>Exclusive</label>
<input id="CampaignType" name="CampaignType" type="radio" value="Shared"><label>Shared</label>
So far, all's well.
But, inside an onclick() event for a button, if I do this:
var values =
{
"CampaignType": $('#CampaignType').val()
}
alert(values.CampaignType);
The alert always comes up as `Exclusive', even if I have changed the selection to 'Shared'.
What do I need to do so that values.CampaignType reflects the what is selected on the page, and not what was set when the page was loaded?
So you can do start with these:
Remove the invalid ids - multiple ids are invalid in CSS. For getting the value of the checked radio button you can use:
$('input[name=CampaignType]:checked').val()
or
$('input[type=radio]:checked').val()
For the label to work you have to link it with the corresponding radio button using the for attribute.
See demo below:
function submit() {
var values = {
"CampaignType": $('input[name=CampaignType]:checked').val()
}
console.log(values.CampaignType);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input checked="checked" id="CampaignType1" name="CampaignType" type="radio" value="Exclusive">
<label for="CampaignType1">Exclusive</label>
<input id="CampaignType2" name="CampaignType" type="radio" value="Shared">
<label for="CampaignType2">Shared</label>
<br/>
<button onclick="submit()">click here</button>
All the best!

Checking a different checkbox hides input field

I have an input field that only shows when the option "Other" is checked. The input field fades out when I uncheck the "Other" checkbox, but I would also like the input field to fade out say if, instead of unchecking the "Other" checkbox I check another checkbox of the same group. Therefore, the "Other" input field should not be visible unless "Other" is checked. I have the javascript partially working, but when I check another checkbox the "Other" input field stays visible.
HTML
<input type="checkbox" id="residence_check" name="found"/>
<label for="residence_check">
Residence
</label>
<input type="checkbox" id="tradeshow_check" name="found"/>
<label for="tradeshow_check">
Tradeshow
</label>
<input type="checkbox" id="office_check" name="found"/>
<label for="office_check">
Office Building
</label>
<input type="checkbox" id="check_other" value="found_other" name="found"/>
<label for="check_other">
Other
</label>
<input type="text" id="check_input" placeholder="Other"/>
Javascript
$('#check_other').change(function() {
if($(this).is(":checked")) {
$('#check_input').fadeIn();
} else {
$('#check_input').fadeOut('fast');
}
});
From what I gather from your use case is that you don't want to use checkboxes, but radio buttons. If that is the case, this would be a good way to implement what you want:
http://jsfiddle.net/AeP58/1/
$('input[type=radio]').on('change', function() { //event on all radio buttons
if($(this).attr('id') == 'check_other' && $(this).prop('checked')) {
$('#check_input').fadeIn();
} else {
$('#check_input').fadeOut('fast');
}
});
If you do want checkboxes, you could change the code a bit and probably get what you want.
If you want to have some fun with checkboxes you could try this:
function showHideOtherInput() {
console.log($(this)[0]==$('#check_other')[0]);
var shouldShow=$('[id$="_check"]:checked').length===0 && $('#check_other').prop('checked');
console.log(shouldShow);
if(shouldShow) {
$('#check_input').fadeIn();
} else {
$('#check_input').fadeOut('fast');
}
}
$('#check_input').hide(); //since nothing is selected at this point just hide the input
$('#check_other').change(showHideOtherInput);
//for each XXXX_check checkbox trigger the show or hide function
$('[id$="_check"]').each(function(ix,el){$(el).change(showHideOtherInput)});
Hope this works for you.
:)

How to identify whether or not a radio has been checked programmatically?

I have a form page in which the user can enter an ID, and the corresponding profile data is pulled from mysql and displayed in the form so that the user may edit it.
One element is a group of radios, so you may select a year level (ie "1", "2", "3", etc).
When a user provides an ID, an AJAX call is made to pre-populate the form with data, including selecting the appropriate radio.
problem:
The user must select a year level to submit the form. I check this with a verifyForm() method:
function verifyForm() {
if( !document.addStudentForm.elements["yearLevel"].checked ) {
alert( "You must select a year level before submitting." );
return false;
}
};
I expect this to check yearLevel and, if an option isn't selected, alert/return false.
However, when the yearLevel radio is pre-selected by the AJAX data, this is still behaving as if the user did not select a radio.
The radio is populated by js via the following code:
document.getElementById( "yearLevel_<?=$student['student']->get('yearLevel')?>" ).checked = true;
edit: Here is the relevant HTML.
<form name="addStudentForm" action="validation/updateStudentValidate.php" method="POST" onSubmit="return verifyForm()">
<input type="radio" value="1" name="yearLevel" disabled id="yearLevel_1" /> 1
<input type="radio" value="2" name="yearLevel" disabled id="yearLevel_2" /> 2
<input type="radio" value="3" name="yearLevel" disabled id="yearLevel_3" /> 3
<input type="radio" value="4" name="yearLevel" disabled id="yearLevel_4" /> 4
<input type="radio" value="5" name="yearLevel" disabled id="yearLevel_5" /> 5
<input type="radio" value="6" name="yearLevel" disabled id="yearLevel_6" /> 6
</form>
Question:
How can I have my javascript properly identify whether or not the radio has been checked, regardless of if it was selected by hand or programmatically?
Taken from this StackOverflow post and adapted for this example and for speed, you can have this in your AJAX success return:
var radios = document.getElementsByName('yearLevel'),
i = radios.length,
isChecked = false;
while(i--){
if (radios[i].checked) {
isChecked = true;
break;
}
}
Then when the function is called:
function verifyForm(){
if(!isChecked){
alert( "You must select a year level before submitting." );
return false;
}
};
This is assuming that you don't have any other items with the name yearLevel in your HTML.
This will actually return the value, I guess I'm unsure if you are wanting to see a specific item checked, or just that they have been checked at all. This function will do both.

Categories

Resources