How does select all checkbox work correctly? - javascript

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>

Related

Checkbox Functionality with Two Series of Checkboxes

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>

How to style specific divs based on checkboxs

Okay so what I want to do is change the style of specific divs based on checkboxes being clicked..
I have several checkboxs like this...
<input type="checkbox" class="the-checkbox" onchange="test()" value="1">
<input type="checkbox" class="the-checkbox" onchange="test()" value="2">
<input type="checkbox" class="the-checkbox" onchange="test()" value="3">
Each of these correspond to a div...
<div class="panel-heading" id="panel-1">
<div class="panel-heading" id="panel-2">
<div class="panel-heading" id="panel-3">
value="1" with id="panel-1, id="panel-2"with id="panel-2" etc
These elements are dynamic and are pulled from a database.
When a checkbox is clicked for example the one with the value="1" I want it to change the colour of the div with "id panel-1".
I also need this to work when multiple checkboxes are checked as this is for styling my "delete entry" functionality.
I am having trouble doing this in javascript here is what I have so far...
function test(){
var checkboxes = document.getElementsByClassName('the-checkbox');
for (var i=0 ; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
var cn = document.getElementsByClassName('panel-heading')[i].id
cn.style.backgroundColor = "red"; // I know this line is incorrect
}
}
}
You are on the right track
The value of the checkbox is the link between the checkbox and the div. Value 1 corresponds to div panel-1 etc. So use the value to get the corresponding div:
correspondingDiv = div with id ("panel-" + value of selected checkbox)
if (checkboxes[i].checked) {
//Get the value of the checkbox
var val = checkboxes[i].value;
//Since the value is the link between the checkbox and the div,
//use it to get the corresponding div
var correspondingDiv = document.getElementById("panel-" + val);
//And apply the background color
correspondingDiv.style.backgroundColor = "red";
}

Hide and show divs on basis of price and category checkboxes in javascript

I am having a div arrangement in which I am defining data attributes. Like I'm displaying a product list in a div with data attributes, namely data-category and data-price. I want to hide and show divs on basis of selection by checkboxes of category and price. Html structure is as follows:
<div class="content" data-category="shoes" data-price="1000">shoe1</div><br />
<div class="content" data-category="shirts" data-price="1200">shirt1</div><br />
<div class="content" data-category="shoes" data-price="2000">shoe2</div><br />
<div class="content" data-category="shoes" data-price="800">shoe3</div><br />
<div class="content" data-category="shirts" data-price="1300">shirt2</div><br />
<div class="content" data-category="shirts" data-price="800">shirt3</div><br />
<input type="checkbox" class="category" category="shoes" id="shoes">shoes
<input type="checkbox" class="category" category="shirts" id="shirts">shirts
For category, I have kept checkboxes, but for price, I need to use range jquery slider I guess, but I'm unable to use that filter. Basically if you select a category from checkbox lets say shoes, then divs only with shoes should get displayed; and then if you filter the results with price some starting and ending limit it should show shoes category divs falling in that specific range. Not out of range.
For example:- we selected shoes checkbox, it should show shoe divs; then if we select range as 1000-2000, then it should show shoe1 and shoe2 and not shoe3. Please help on this.
Since "category" is not a valid attribute name in html, you should use something else instead. In this case, it would be natural to just use the id directly, as this is the values you need anyway:
<input type="checkbox" class="category" id="shoes">shoes
<input type="checkbox" class="category" id="shirts">shirts
For range, you could have something like this:
<input type="radio" name="range" value="0-9000" checked>All
<input type="radio" name="range" value="0-999">0-1000
<input type="radio" name="range" value="1000-2000">1000-2000
Then in the javascript:
$("input.category").prop("checked", true).change(function (e) {
//Trigger change event on active price range item where the filter is applied
$("input[name=range]:checked").trigger("change");
});
$("input[name=range]").change(function (e) {
var toggle = this.checked;
var range = this.value.split('-');
var rangeFrom = parseInt(range[0]);
var rangeTo = parseInt(range[1]);
// If all category checkboxes are off we will ignore category filter
var allOff = ($("input[type=checkbox]:checked").length === 0);
$(".content[data-price]").each(function(){
var $this = $(this);
// Check if category is active
var active = allOff || $("#" + $this.data("category")).prop("checked");
// Get price as number
var price = parseFloat($this.data('price'));
// Toggle visibility based on category and price range
$this.toggle(price >= rangeFrom && price <= rangeTo && active );
});
});

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.
:)

Javascript display same content on each checkbox clicks?

I have multiple check boxes and i want them to display the same content when each of them is clicked. Now when I click on one check box, the content appears, but until I unclick it the next checkbox won't display any content. I want the all the contents to be displayed as long as check boxes are clicked. any tip with this.
I tried this:
function showTime(days){
var showTime = document.getElementById("time_schedules");
var days = document.getElementById("schedule");
if (days.checked) {
showTime.style.display = "Block";
}
else{
showTime.style.display = "none";
}
}
Insert some class attribute to all your checkboxes so you can select them, then capture the click event, iterate over all checkboxes and perform whatever you need to do (setting label etc).
I recommend using some javascript library such as jquery, for example:
<input type="checkbox" name="cb1" class="cb" />
<label for="cb1" class="cblabel">label1</label>
<input type="checkbox" name="cb2" class="cb" />
<label for="cb2" class="cblabel">label2</label>
$('.cb').bind('click', function() {
$('.cblabel').each(function(i,v) { v.innerHTML = 'hello'; });
});
http://jsfiddle.net/3EMyY/

Categories

Resources