29

Here is my code :

It actually count checked checkboxes and write it inside <span class="counter"></span>. This code works on Firefox, but not on Chrome.

On Chrome, the .select_all check all checkboxes I want, but doesn't update the counter. Actually counter get updated when I uncheck the .select_all, which is weird.

IMPORTANT FACT: I don't want to count the .Select_all checkboxes inside my .counter

jQuery(document).ready(function($){

$(function() {
    $('#general i .counter').text(' ');

    var generallen = $("#general-content input[name='wpmm[]']:checked").length;
    if(generallen>0){$("#general i .counter").text('('+generallen+')');}else{$("#general i .counter").text(' ');}
})

$("#general-content input:checkbox").on("change", function() {
    var len = $("#general-content input[name='wpmm[]']:checked").length;
    if(len>0){$("#general i .counter").text('('+len+')');}else{$("#general i .counter").text(' ');}
});


$(function() {
    $('.select_all').change(function() {
        var checkthis = $(this);
        var checkboxes = $(this).parent().next('ul').find("input[name='wpmm[]']");

        if(checkthis.is(':checked')) {
            checkboxes.attr('checked', true);
        } else {
            checkboxes.attr('checked', false);
        }
    });
});

});

EDIT: Here is a example document of the code : http://jsfiddle.net/8PVDy/1/

hawkidoki
  • 349
  • 1
  • 3
  • 10
  • why don't you try simple javascript – polin Feb 06 '13 at 09:50
  • Can you provide a working [jsFiddle](http://jsfiddle.net) that demonstrates the problem? – Anthony Grist Feb 06 '13 at 09:51
  • 1
    see this post..http://stackoverflow.com/questions/8011556/how-to-count-check-boxes-using-jquery – Rinku Feb 06 '13 at 09:56
  • Do you get any javascript errors? Why isn't the .on block not inside a jquery ready function? – Andy Feb 06 '13 at 09:58
  • Here is the Working Document : http://jsfiddle.net/8PVDy/1/ – hawkidoki Feb 06 '13 at 10:01
  • Please see ["Should questions include “tags” in their titles?"](http://meta.stackexchange.com/questions/19190/should-questions-include-tags-in-their-titles), where the consensus is "no, they should not"! –  Feb 03 '16 at 13:31

7 Answers7

64

You can use a function to update the counter :

function updateCounter() {
    var len = $("#general-content input[name='wpmm[]']:checked").length;
    if(len > 0){
       $("#general i .counter").text('('+len+')');
    } else { 
       $("#general i .counter").text(' ');
    }
}

and call this function when a checkbox's state is changed (including the selectAll checkboxes)

Here is an updated jsFiddle : http://jsfiddle.net/8PVDy/4/

Kopi Bryant
  • 1,300
  • 1
  • 15
  • 30
gabitzish
  • 9,535
  • 7
  • 44
  • 65
43
$('input[type="checkbox"]:checked').length
nbrooks
  • 18,126
  • 5
  • 54
  • 66
11

you can do it this way

$(document).ready(function(){
$('input[type="checkbox"]').click(function(){
    alert($('.test:checked').length);

});
});

HTML i used

<input type="checkbox" name="test" class="test" value=""/>  
<input type="checkbox" name="test" class="test" value=""/>  
<input type="checkbox" name="test" class="test" value=""/>  
<input type="checkbox" name="checkAll" class="checkAll" value=""/>

Hope this helps

Roger
  • 1,693
  • 1
  • 18
  • 34
2

For updating the checked status use the jQuery.prop() function

Code:

$(function(){
    $('#general i .counter').text(' ');

    var fnUpdateCount = function() {
        var generallen = $("#general-content input[name='wpmm[]']:checked").length;
        console.log(generallen,$("#general i .counter") )
        if (generallen > 0) {
            $("#general i .counter").text('(' + generallen + ')');
        } else {
            $("#general i .counter").text(' ');
        }
    };

    $("#general-content input:checkbox").on("change", function() {
                fnUpdateCount();
            });

    $('.select_all').change(function() {
                var checkthis = $(this);
                var checkboxes = $("#general-content input:checkbox");

                if (checkthis.is(':checked')) {
                    checkboxes.prop('checked', true);
                } else {
                    checkboxes.prop('checked', false);
                }
                fnUpdateCount();
            });
});

Demo: Fiddle

Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
1

What I found missing in all above answers is an explanation about how to listen to clicks in an efficient way since the question is tightly coupled with onChange event. Another thing is that question doesn't specify whether the code should be only in Jquery I think that adding vanilla JS solution should be a good idea.

Here's the HTML list of checkboxes the I will be counting. I have approched the question in a little bit more generic way, to make it easier to apply in different conditions. I plan to count checkboxes globally and per each section.

<div class="wrapper">
  <section class="list list-1">
    <label for="id-11"><input type="checkbox" id="id-11"></label>
    <label for="id-12"><input type="checkbox" id="id-12"></label>
    <label for="id-13"><input type="checkbox" id="id-13"></label>
    <label for="id-14"><input type="checkbox" id="id-14"></label>
    <label for="id-15"><input type="checkbox" id="id-15"></label>
    <label for="id-16"><input type="checkbox" id="id-16"></label>
    <label for="id-17"><input type="checkbox" id="id-17"></label>
    <label for="id-18"><input type="checkbox" id="id-18"></label>
    <label for="id-19"><input type="checkbox" id="id-19"></label>
    <label for="id-110"><input type="checkbox" id="id-110"></label>
    <span class="list-score">Section 1: <span class="number">0</span></span>
  </section>

  <section class="list list-2">
    <label for="id-21"><input type="checkbox" id="id-21"></label>
    <label for="id-22"><input type="checkbox" id="id-22"></label>
    <label for="id-23"><input type="checkbox" id="id-23"></label>
    <label for="id-24"><input type="checkbox" id="id-24"></label>
    <label for="id-25"><input type="checkbox" id="id-25"></label>
    <label for="id-26"><input type="checkbox" id="id-26"></label>
    <label for="id-27"><input type="checkbox" id="id-27"></label>
    <label for="id-28"><input type="checkbox" id="id-28"></label>
    <label for="id-29"><input type="checkbox" id="id-29"></label>
    <label for="id-210"><input type="checkbox" id="id-210"></label>
    <span class="list-score">Section 2: <span class="number">0</span></span>
  </section>

  <section class="list list-3">
    <label for="id-31"><input type="checkbox" id="id-31"></label>
    <label for="id-32"><input type="checkbox" id="id-32"></label>
    <label for="id-33"><input type="checkbox" id="id-33"></label>
    <label for="id-34"><input type="checkbox" id="id-34"></label>
    <label for="id-35"><input type="checkbox" id="id-35"></label>
    <label for="id-36"><input type="checkbox" id="id-36"></label>
    <label for="id-37"><input type="checkbox" id="id-37"></label>
    <label for="id-38"><input type="checkbox" id="id-38"></label>
    <label for="id-39"><input type="checkbox" id="id-39"></label>
    <label for="id-310"><input type="checkbox" id="id-310"></label>
    <span class="list-score">Section 3: <span class="number">0</span></span>
  </section>

  <span class="total-score">Total: <span class="number">0</span></span>
</div>


and here's the JS markup, that listens to all clicks inside the .wrapper div and counts selected inputs in the context of the .wrapper and each .list section.

const total = document.querySelector('.total-score .number')

document.querySelector('.wrapper').addEventListener('change', function(event) { // First we apply the ONLY one listener to do the listening for us - we don't need listener on each checkbox
  const numberAll = this.querySelectorAll('input[type="checkbox"]:checked').length // We count all selected inputs in side the main wrapper. 
  total.innerHTML = numberAll // We update the total counter

  const list = event.target.closest('.list') // We look and cache the closest section, wrapping the clicked checkbox element
  const numberList = list.querySelectorAll('input[type="checkbox"]:checked').length // Once found, we start to count the number of selected checboxes under the section
  list.querySelector('.list-score .number').innerHTML = numberList // We update the sectiona relevant counter
})

Here's the live example in the JS fiddle: https://jsfiddle.net/mkbctrlll/yak4oqj9/159/

In Vanilla JS you have to be aware that applying the change listener to each checkbox is much slower solution. Instead you should make use of so called event delegation and apply the listener to the wrapping element or even to whole document.

Here you can check it by yourself, how much slower is listening to change per each input in your list:

https://jsperf.com/change-listener-on-each-vs-event-delegation/1

The code for the slower option (just to compare):

document.querySelector('.wrapper').addEventListener('change', function() {
    const numberAll = this.querySelectorAll('input[type="checkbox"]:checked').length
    total.innerHTML = numberAll
  })

document.querySelectorAll('.list').forEach((list) => {
  list.addEventListener('change', function() {
    const numberAll = this.querySelectorAll('input[type="checkbox"]:checked').length
    this.querySelector('.list-score .number').innerHTML = numberAll
  })
})

and my solution in jQuery:

$('.wrapper').change(function() {
  const numberAll = $(this).find('input[type="checkbox"]:checked').length
  total.innerHTML = numberAll

  const $list = $(event.target).closest('.list')
  const numberList = $list.find('input[type="checkbox"]:checked').length
  $($list.find('.list-score .number')).html(numberList)
})

P.S. I tried adding jQuery solution to the benchmark too, but it's performance seemed to be fake, so I decided to go without it.

mkbctrl
  • 113
  • 6
0

Try this.

$('.select_all').change(function() {
var num = $(this).find("input[name='wpmm[]']:checked").length;
$("#general .counter").html(num);
});
KBN
  • 2,915
  • 16
  • 27
0

Modified the select all-handler to trigger the onchange function for the sub-category checkboxes like this

$(function() {
    $('.select_all').change(function() {
        var checkthis = $(this);
        var checkboxes = $(this).parent().next('ul').find("input[name='wpmm[]']");

        if(checkthis.is(':checked')) {
            checkboxes.attr('checked', true);
        } else {
            checkboxes.attr('checked', false);
        }
        // make sure to trigger the onchange behaviour for the checkboxes
        $("#general-content input:checkbox").change();
    });
})

I seem to remember that there is a prettier way to trigger them, but can't find it

Ledhund
  • 1,228
  • 10
  • 24