Iterate over checkboxes array to determine if checked - javascript

I have a table with a "select all" checkbox. When I populate this table, all of the items that have been selected previously are checked. Currently, the "select all" checkbox will return checked even if not all of items are checked. I'm trying to create a function that will iterate over each checkbox, and if all are checked, then it will automatically toggle the select all checkbox. Same logic if not all items are selected - the select all checkbox will not be selected.
Here's the code I have so far:
function unclickSelectAll(parent) {
var $checkboxes = parent.find('input[type="checkbox"]');
var $selectAllCheckbox = $checkboxes.filter('.vendor');
var $invoiceCheckBoxes = $checkboxes.filter('.invoice');
$invoiceCheckBoxes.each(function(i, c) {
var checkbox = $(this);
if (checkbox[i].checked) {
$selectAllCheckbox.prop('checked', true);
} else {
$selectAllCheckbox.prop('checked', false);
}
});
};
What happens currently is that it will loop over the first checkbox, and if it's checked it will change the checked property of the select all check box to true. Then through the next loop I get an error that it cannot find the 'checked' property of checkbox[i];

you can do something like
$('.invoice:checkbox').click(function () {
unclickSelectAll();
});
function unclickSelectAll() {
var allSelected = $('.invoice:checked:checkbox').length === $('.invoice:checkbox').length;
$('.vendor:checkbox').prop('checked', allSelected);
}
plunker: http://plnkr.co/edit/iSrpfjd4Z7FUIhQkewcF?p=preview

You're switching the state of the select-all checkbox after testing each checkbox, so the final state will just be based on the last checkbox. You need to test whether all the checkboxes are checked. You can do this by simply counting the number of checkboxes and the number of checked checkboxes; if the count is the same, they're all checked.
if (parent.find(':checkbox').length == parent.find(':checkbox:checked').length) {
$selectallCheckbox.prop('checked', true);
} else {
$selectallCheckbox.prop('checked', false);
}

Related

How to check if a checkbox is checked when programmatically added? [duplicate]

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 8 months ago.
Is there a way to check if a checkbox is checked when you programmatically add another checkbox? For example, if I have a function that adds a checkbox and then it's checked and then add another checkbox, the second checkbox determines if the first checkbox is selected or not. If the first checkbox is selected, don't show the second added checkbox. If the first checkbox is not selected, you can check the second checkbox and the first one is hidden.
The code I have below is suppose to hide any checkbox that's added after the first checkbox is selected.
$(document).on( "click", '.add', function() {
// programmatically add checkboxes
$('.add').after("<div id='cover_photo_set_featured'><input type='checkbox'></input>Set featured image</div><div class='add2'>+add</div>").remove();
});
$(document).on( "click", '.add2', function() {
$('.add2').after("<div id='cover_photo_set_featured'><input type='checkbox'></input>Set featured image</div>").remove();
});
// function to check is checkboxes are selected
if ($("#cover_photo_set_featured input").is(':checked')) {
$('#cover_photo_set_featured input[type=checkbox]').each(function() {
//Check if the box is checked
var x = $(this).is(':checked');
//if checkbox is NOT checked
if(x === false) {
//Hide the choice
$(this).parent().hide();
}
});
} else {
$('#cover_photo_set_featured input[type=checkbox]').parent().show();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="add">+add</div>
In javascript you can only add events to elements already on the DOM.
To achive what you want. you have to reassign events everytime you add a checkbox.
I would recommend adding a function that adds event listeners like so:
function setup() {
if ($("#cover_photo_set_featured input").is(':checked')) {
$('#cover_photo_set_featured input[type=checkbox]').each(function() {
//Check if the box is checked
var x = $(this).is(':checked');
//if checkbox is NOT checked
if(x === false) {
//Hide the choice
$(this).parent().hide();
}
});
} else {
$('#cover_photo_set_featured input[type=checkbox]').parent().show();
}
}
then calling it whenever you add a new checkbox.

Checkbox not printing after restoring values from localstorage

We have some checkboxes in our code when selecting checkbox and executing window.print(), checked boxes is displayed. But when we reset items and Restore again and after that if we execute window.print() selected checkboxes are not displayed.
Here is code for storing checkbox into localstorage
$('input[type="checkbox"]').each(function() {
let id = $(this).attr('id');
var checkbox = document.getElementById(id);
localStorage.setItem(id, checkbox.checked);
});
Get checkbox values from localstorage
$('input[type="checkbox"]').each(function() {
let id=$(this).attr('id');
var checked = JSON.parse(localStorage.getItem(id));
document.getElementById(id).checked = checked;
});

Select All Checkboxes while keeping track of manual selects jquery

I've been using a simple select all script for checkboxes for a while now that looks something like this:
<span id="select">Select All</span>
with
$('#select').click(function(event) {
var $that = $(this);
$('.checkbox').each(function() {
this.checked = $that.is(':checked');
});
});
It's fairly simple. It attaches to an onclick, loops through all the inputs with the class .checkbox and checks or unchecks them accordingly. However what I'd like to do now is make it a bit more user friendly adding the following functionality to it.
1) When the user click the link labeled "Select All" it should select all check boxes as normal, but then change the text to "Deselect All". Similarly, when the user clicks "Deselect All" the text would go back to "Select All".
2) If the users manually select all check boxes I'd like check for this scenario and update the text from Select All to Deselect All as well.
Your code is checking whether a <span> is :checked, which as far as I know is not possible. Perhaps I'm wrong, but in this answer I'll use a different approach to keeping track of that, a data attribute.
// initialize 'checked' property
$('#select').data('checked', false);
// make link control all checkboxes
$('#select').click(function(event) {
var $that = $(this);
var isChecked = ! $that.data('checked');
$that.data('checked', isChecked).html(isChecked ? 'Deselect All' : 'Select All');
$('.checkbox').prop('checked', isChecked);
});
// make checkboxes update link
$('.checkbox').change(function(event) {
var numChecked = $('.checkbox:checked').length;
if (numChecked === 0) {
$('#select').data('checked', false).html('Select All');
} else if (numChecked === $('.checkbox').length) {
$('#select').data('checked', true).html('Deselect All');
}
});
Not jquery, but here's what I'd do
var cb=document.getElementsByClassName('cb'); //get all the checkboxes
var selectAll=document.getElementById('selectAll'); //get select all button
function selectAllState(inputEle,selectAllEle){ //class to manage the states of the checkboxes
var state=1; //1 if button says select all, 0 otherwise;
var num=inputEle.length;
function allChecked(){ //see if all are checked
var x=0;
for(var i=0;i<num;i++){
if(inputEle[i].checked==true){
x+=1;
}
}
return x;
}
function handler(){ //if all checked or all unchecked, change select all button text
var y=allChecked()
if( y==num && state){
selectAllEle.innerHTML='Deselect All';
state=0;
} else if(y==0 && !state){
selectAllEle.innerHTML='Select All';
state=1;
}
}
for(var i=0;i<num;i++){
inputEle[i].addEventListener('change',handler); //listen for changes in checks
}
function checkAll(){ //function checks or unchecks all boxes
for(var i=0;i<num;i++){
inputEle[i].checked=state;
}
handler();
}
selectAll.addEventListener('click',checkAll); //listen for button click
}
var myState=new selectAllState(cb,selectAll); //instance the selectAllState class
This creates a javascript class to manage the states of all your checkboxes. It takes two arguments, the first being the array of checkboxes (which is what you get if you use getElementsByClassName), and the second being the select all button. The internal methods could be exposed using the this keyword if you want to be able to, for example, have a different part of the application select or deselect all the checkboxes.
Try breaking it down in several functions: Let's call the span toggle, as it can select and de-select all.
<span id="toggle">Select All</span>
And we'll have a function to select and de-select all of the values. No need to iterate through the list as prop sets the value for all elements
function SetAll(value){
$(".checkbox").prop("checked", value);
}
Then for the toggle button:
$("#toggle").click(function(){
if($(this).text() == "Select All"){
SetAll(true);
$(this).text("De-select All");
} else {
SetAll(false);
$(this).text("Select All");
}
});
Finally we need an onchange event for each checkbox:
$(".checkbox").change(function(){
var allCheckboxes = $(".checkbox");
var allChecked = $.grep(allCheckboxes, function(n,i){
return $(n).is(":checked");
}); //grep returns all elements in array that match criteria
var allUnchecked = $.grep(allCheckboxes, function(n,i){
return $(n)is(":checked");
},true); //invert=true returns all elements in array that do not match
// check the lengths of the arrays
if (allChecked.length == allCheckboxes.length)
$("#toggle").text("De-select All");
if (allUnchecked.length == allCheckboxes.length)
$("#toggle").text("Select All");
}):

Uncheck row checkbox if inputs are empty on blur?

I have 2 issues here. Clicking an input on a row should check the row's checkbox. Currently, only the first text input will check the checkbox because of .prev(). Is there a different way to do this? All inputs for that row should check that row's checkbox.
// check checkbox for clicked row
$('table').on('click', 'input[type=text]', function () {
$(this).closest('td').prev().find('input').prop('checked', true);
});
Also, the second block of code isn't working as it should. If you focus on a different row, if the text inputs from the previous (or any) row are blank - remove the checkbox. The checkbox will be a save, and there is no point of saving blank text inputs.
// remove check in inputs are empty for that row
$('input[type=text]').blur(function () {
$('table tr').each(function () {
if ($(this).find('input[type=text]:empty').length()) {
$('td').find('input').prop('checked', false);
}
});
})
http://jsfiddle.net/Ldge5qzn/
Find the closest tr instead and then find the inputs that are checkboxes and set the checked property
$(this).closest('tr').find('input[type=checkbox]').prop('checked', true);
For the second part, the :empty selector tests against the element having child elements not against empty values so that has to also be modified. Loop through each rows text inputs set a flag if any of them are not empty. Set checkbox accordingly
$('table tr').each(function () {
var emptyRow = true;
$(this).find("input[type=text]").each(function(){
if($(this).val().length > 0) {
emptyRow = false;
}
});
if (emptyRow) {
$(this).find('input[type=checkbox]').prop('checked', false);
}
});
JSFiddle Demo
You can do it by checking the closest tr - then finding the checkbox in that tr
$('table').on('click', 'input[type=text]', function () {
$(this).closest('tr').find('input[type=checkbox]').prop('checked', true);
});
Same thing with the second problem - check using the closest tr
Then you can use filter to get all the text inputs with values
Then check the length to see if there are any inputs returned - and set the checked property accordingly using .prop('checked',function()
$('input[type=text]').blur(function () {
var $tr = $(this).closest('tr'); // get closest tr
// get all of input[type=text] with value in that row
var inputsWithValue = $tr.find('input[type=text]').filter(function () {
return $.trim(this.value).length;
});
// set the checked to true if any element has value - else set checked to false
$tr.find('input[type=checkbox]').prop('checked', function () {
return inputsWithValue.length;
}).length;
});
FIDDLE
have a look at this .Hope this helps ...
$('table').on('click', 'input[type=text]', function () {
$(this).closest('td').parent('tr').find('input[type="checkbox"]').prop('checked', true);
});
full code below :-
JSFiddle

Disable button if all checkboxes are unchecked and enable it if at least one is checked

I have a table with a checkbox in each row and a button below it. I want to disable the button if at least one checkbox is checked.
<tbody>
<tr>
<td>
<input class="myCheckBox" type="checkbox"></input>
</td>
</tr>
</tbody>
<button type=submit id="confirmButton"> BUTTON </button>
The jQuery I came up with to accomplish this is the following:
$('tbody').click(function () {
$('tbody tr').each(function () {
if ($(this).find('.myCheckBox').prop('checked')) {
doEnableButton = true;
}
if (!doEnableButton) {
$('#confirmButton').prop('disabled', 'disabled')
}
else {
$('#confirmButton').removeAttr("disabled");
}
});
});
Naturally, this does not work. Otherwise I would not be here. What it does do is only respond to the lowest checkbox (e.g., when the lowest button is checked/unchecked the button is enabled/disabled).
I made a JSFIddle here although it does not show the same behaviour as locally.
Does any know how I can accomplish that it responds to all checkboxes and disables the button if they are ALL disabled?
Try this:
var checkBoxes = $('tbody .myCheckBox');
checkBoxes.change(function () {
$('#confirmButton').prop('disabled', checkBoxes.filter(':checked').length < 1);
});
checkBoxes.change(); // or add disabled="true" in the HTML
Demo
Explanation, to what I changed:
Cached the checkbox element list/array to make it a bit faster: var checkBoxes = $('tbody .myCheckBox');
removed the if/else statement and used prop() to change between disable= true/false.
filtered the cached variable/array checkBoxes using filter() so it will only keep the checkboxes that are checked/selected.
inside the second parameter of prop added a condition that will give true when there is more than one checked checkbox, or false if the condition is not met.
Add an event handler that fires when a checkbox is changed, and see if there are any checked boxes, and set the disabled property appropriately :
var boxes = $('.myCheckBox');
boxes.on('change', function() {
$('#confirmButton').prop('disabled', !boxes.filter(':checked').length);
}).trigger('change');
FIDDLE
Try this:
$('tbody').click(function () {
if ($('.myCheckBox:checked').length >= 1) {
$('#confirmButton').prop("disabled", true);
}
else {
$('#confirmButton').prop("disabled", false);
}
});
DEMO
Try this one:
let $cbs = $(".myCheckBox").change(function() {
if ($cbs.is(":checked")){
// disable #confirmButton if at least one checkboxes were checked
$("#confirmButton").prop("disabled", false);
} else {
// disable #confirmButton if all checkboxes were unchecked
$("#confirmButton").prop("disabled", true);
}
});

Categories

Resources