Select All Checkboxes while keeping track of manual selects jquery - javascript

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");
}):

Related

Iterate over checkboxes array to determine if checked

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);
}

How to validate a memorized value in an input box

I have the following code:
$(":input").bind("keyup change", function(e) {
var comboVal = $('.emailrequerido1').val()+$('.emailrequerido2').val()+$('.emailrequerido3').val()+$('.emailrequerido4').val()+$('.emailrequerido5').val();
if(comboVal == 'nullnull' || comboVal == ""){
$("#enviarForm").attr('disabled', true);
}else{
$("#enviarForm").removeAttr('disabled');
}
});
What I am trying to accomplish is that when you select a memorized value from the input box by double clicking in the box a history of inputs shows (these values are saved by the browser (I believe)) and if you choose one of these and the field has that text you selected the button should enable.
Here is a JSFiddle example: JSFiddle example
In the example I added a value to the first field since these dont memorize as I expalined before to show a demonstration of what I mean.
I have cleaned up the code a bit: http://jsfiddle.net/kam5B/1/
I've swapped the classes and ids so that the ids are unique, and the classes are common.
Here is a checkEmails function that runs the validation and enables/disables the checkbox.
checkEmails is run every time an input changes, and when the page loads the first time:
$(document).ready(function () {
function checkEmails() {
var nonempty = $('form .email_contactopadrino').filter(function() {
return $(this).val() != '';
});
if (nonempty.length) {
$('#enviarForm').removeAttr('disabled');
}
else {
$('#enviarForm').attr('disabled', true);
}
};
$('form').on('keyup change', '.email_contactopadrino', checkEmails);
checkEmails();
});

Javascript iterate through all checkboxes on submit, and set attribute if changed from original value

I am trying to make a javascript function similar to the following, except it will iterate through all the checkboxes when the user clicks the submit button:
$('.checkboxstatus').click(function(){
this.setAttribute('checked',this.checked);
if (this.checked && $(this).data("def") == 0){
//checkbox has changed
this.setAttribute('changed', 'yes');
}
else if(!this.checked && $(this).data("def") == 'checked')
{
//checkbox has changed
this.setAttribute('changed', 'yes');
}
else{
//no change in checkbox
this.setAttribute('changed', 'no');
}
});
When the user clicks submit, the function should be called and it should iterate through all checkboxes and see if the checkbox is checked and see if the data-def is checked or 0. If the checkbox is checked and data-def="checked" then nothing should happen. If the checkbox state is different from the data-def then an attribute ("changed") should be added to that checkbox with value of "yes". Any suggestions on how to go about this?
Your question almost gives you the answer. You need to attach a "submit" event handler to the form, then grab all input[type=checkbox] and set the "changed" attribute accordingly.
I'm not sure I get this, but the usual way to do something like this would be to set an initial state in data, then on submit, prevent the submit action, check all the checkboxes against that initial state data variable, and see if anything changed, if it did, trigger the native submit handler ?
var boxes = $('input[type="checkbox"]').each(function() {
$(this).data('initial_state', this.checked);
});
$('form').on('submit', function(e){
e.preventDefault();
var same_same = true;
boxes.each(function() {
if ( $(this).data('initial_state') !== this.checked ) { // has changed ?
$(this).data('changed', true);
same_same = false;
}
});
if ( ! same_same ) { // diffelent
this.submit();
} else {
alert('same same, but not diffelent!');
}
});

jQuery .each() does not update

I am trying to check if a set of radio buttons has been selected. However, it seems that it does not update if a radio is selected after the fact.
The code:
$('button#submit').click(function() {
var addr_chkd = 0;
$('input:radio[name="address"]').each(function() {
if (!$(this).attr('checked'))
addr_chkd++
});
});
if (addr_chkd)
// do something
When the button is clicked and nothing is selected, the code works great. However, when a radio button is selected and the button is clicked, addr_chkd still returns a value greater than zero.
[UPDATE]
The issue is that I'm checking for addr_chkd greater than zero. I should be checking if addr_chkd is equal to the length of the radio buttons. I made a slight modification to #PPvG's answer and it did the trick.
$('button#submit').click(function() {
var radios = $('input:radio[name="address"]');
var num_unchecked = radios.filter(':not(:checked)').length;
if (num_unchecked === radios.length) {
alert('please select a button');
}
});
try this
$('button#submit').click(function() {
var addr_chkd = 0;
$('input:radio:[name="address"]').each(function() {
if (!$(this).is(':checked'))
addr_chkd++
});
});
or you can simply do it as
$('button#submit').click(function() {
var addr_chkd = $('input:radio[name="address"]:not(:checked)').length
}
since at a time only one radio button can be checked so you can also do as
$('button#submit').click(function() {
var addr_chkd = $('input:radio[name="address"]').length - 1;
}
fiddle example for all the above : http://jsfiddle.net/pdm2F/
I'm not entirely clear on what you're trying to do, but I can interpret addr_chkd in two ways.
If the "addr" stands for "adder", and you want to count the number of unchecked radio buttons, use this:
$('button#submit').click(function() {
var radios = $('input:radio[name="address"]');
var num_unchecked = radios.filter(':not(:checked)').length;
if (num_unchecked) {
// do something
}
});
If, on the other hand, "addr" means "address", and you want the index of the selected radio button, use this:
$('button#submit').click(function() {
var radios = $('input:radio[name="address"]');
var checked = radios.filter(':not(:checked)').get(0);
if (checked.length > 0) {
var index_checked = radios.index(checked);
// do something
}
});
Note that in both cases, I moved the if clause inside the click handler. In your example, it was outside the click handler, which means it would be executed only once, and even before the button was clicked.
You can use a much easy way:
var addr_chkd = $('input:radio[name="address"]:checked').length;
Or if you mean not checked:
var addr_chkd = $('input:radio[name="address"]').not(':checked').length;
But for the radio input, you may do something wrong.
Use $(this).attr() instead of this.

jQuery unbinding click event on a radio button that is already selected

I am trying to create some parametric filters but i do not want to invoke the function that makes my search AJAX call when a radio button filter is already selected.
$('#contentType input:enabled').bind('click', function(e){
var $this = $(this),
$type = this.type,
$id = this.id;
if ($type === 'radio') {
if ($id === 'allContent'){
sFrm.$boxes.attr({'checked': false});
sFrm.$specificRadio.attr({'disabled': true});
searchAjax();
removeFilter();
}
} else if ($type === 'checkbox') {
if (sFrm.$boxes.filter(':checked').length === 0) {
sFrm.$allRadio.trigger('click');
} else {
var filterConfig = {
index: $('.subFilter').index($this),
txt: jQuery.trim($this.parent().text())
}
sFrm.$allRadio.attr({'checked': false});
sFrm.$specificRadio.attr({'disabled': false, 'checked': true});
searchAjax();
if ($this.is(':checked')) {
addFilter(filterConfig);
} else {
removeFilter(filterConfig.index);
}
}
}
});
So the jQuery above looks at ALL enabled inputs in the collection and when a user clicks the allContent radio button the searchAjax function is invoked.
This is correct when said radio button is not already selected/checked. At the moment the function is still invoked when the button is selected and i would like to stop this behaviour but cannot figure out how?
EDIT
Not sure i explained correctly. Hopefully this jsFiddle will help:
http://jsfiddle.net/QsbRp/3/
Basically if All content types is checked already and is clicked when checked then searchAjax should not be invoked. It currently invokes the function.
When it is not checked and clicked then it should behave as it is now (disable sibling radio button and uncheck all associated checkboxes).
Add at the top of your handler:
if ($this.is(":checked")) {
return;
}
The event handler will return and not execute the rest of the function if the radio button is currently selected.

Categories

Resources