evanburen
evanburen

Reputation: 309

Looping through checkboxes and subtracting a value

I have a series of checkboxes and each is worth a different amount of points that I want to deduct from a total of 100 if the box is not checked. The point value is designated by the CSS class of the checkbox. In this example, each box is worth 10 points so if both remain checked, the point value = 100, 1 unchecked = 90, 2 unchecked = 80 etc. Similarly, if a user decides to check the box back again, I need to add the 10 points back to the total.

$(document).ready(function () {
$('[class*="Score"]').change(function () {
    calculateScore();
});

function calculateScore() {
    var total = 100;
    $(".Score10").each(function () {
        if ($(this).is(':checked)')) {
            total += 10;
        } else {
            total -= 10;
        }});

<asp:CheckBox ID="chkScore_Greeting" runat="server" CssClass="Score10" 
Checked="true" /> 
<asp:CheckBox ID="chkScore_Authentication" runat="server" 
CssClass="Score10" Checked="true" />

Upvotes: 0

Views: 221

Answers (3)

Tibrogargan
Tibrogargan

Reputation: 4603

I've given you two flavors of the same thing. Both implement the "each worth different points" thing using the built-in dataset properties of DOM elements.

Version 1: Subtract the weight of anything not checked from 100.

$(document).ready(function () {
  $(document).on('change', '.Score', function() {
    var score = 100 - $('.Score:not(:checked)').toArray().reduce(
      (acc, cur) => acc + parseInt(cur.dataset.weight), 0);
    console.log(score);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" name="thing1" data-weight="10" class="Score" checked="true"/>1<br />
<input type="checkbox" name="thing2" data-weight="5" class="Score" checked="true"/>2<br />

Version 2: Modify the current score by the weight of the checkbox that was selected/unselected.

var score = 100;

$(document).ready(function () {
  $(document).on('change', '.Score', function() {
    score += parseInt(this.dataset.weight) * (this.checked?1:-1)
    console.log(score);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" name="thing1" data-weight="10" class="Score" checked="true"/>1<br />
<input type="checkbox" name="thing2" data-weight="5" class="Score" checked="true"/>2<br />

Upvotes: 1

Obsidian Age
Obsidian Age

Reputation: 42304

Your problem is two-fold.

First, you need to set your variable total outside of the function calcuateScore(). As it stands, whenever your checkboxes change, the total gets set to 100, and then the logic triggers.

Second, your jQuery toggle won't work as you're passing in the wrong $(this) reference (as you want the one you clicked on, not to loop over each of them). In order to resolve this, you'll want to pass through the JavaScript version of this as a parameter in the call to calculateScore(). Then you can just check whether that element is checked with .ischecked.

This can be seen in the following working example, where I've substituted the ASP checkboxes for HTML ones:

$(document).ready(function() {

  $('[class*="Score"]').change(function() {
    calculateScore(this);
  });

  var total = 100;

  function calculateScore(checkbox) {
    if (checkbox.checked) {
      total += 10;
    } else {
      total -= 10;
    }
    console.log(total);
  };

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="checkbox" class="Score10" checked="true" />
<input type="checkbox" class="Score10" checked="true" />

Hope this helps! :)

Upvotes: 1

Jeff Matthews
Jeff Matthews

Reputation: 592

Stop adding 10. You are already starting with 100. The only thing left to do is subtract 10 for each one that is not checked. In other words, you only need the "else" part of your condition.

Upvotes: 0

Related Questions