Andrew Nguyen Andrew Nguyen - 25 days ago 8
jQuery Question

Counting items using .length on click producing incorrect value

Objective




  • A button should be able to be selected and clicking that same button
    should then unselect that button

  • When the number of buttons with the class of
    is-selected === 3
    change the cursor behaviour using to
    pointer-events: none
    unless a button is unselected first



Problem



I have a series of buttons
btn--like
and when I unselect a button it
countLike
, which is counting the number of buttons with the class
is-selected
. The unexpected behaviour is that I click three buttons and then when I click a previously selected button to unselect it,
countLike is 4, instead of 2


scripts.js



$(".btn--like").on("click", function(){
let countLike = ($(".btn--like.is-selected").length) + 1;
console.log(countLike);

$(this).toggleClass("is-selected");
$(this).children(".fa-check").toggleClass("is-grey");
$(this).children(".fa-check").toggleClass("is-red");

if (countLike === 3) {
$(".btn--like:not(.is-selected)").css("pointer-events", "none");
} else {
$(".btn--like").css("pointer-events", "auto");
}
});


index.html



<div class="button__group">
<button class="btn btn--option btn--like">Jewelry <i class="fa fa-check is-grey" aria-hidden="true"></i></button>
<button class="btn btn--option btn--like">Scarves <i class="fa fa-check is-grey" aria-hidden="true"></i></button>
<button class="btn btn--option btn--like">Fishing <i class="fa fa-check is-grey" aria-hidden="true"></i></button>
<button class="btn btn--option btn--like">Cologne <i class="fa fa-check is-grey" aria-hidden="true"></i></button>
<button class="btn btn--option btn--like">Shirts <i class="fa fa-check is-grey" aria-hidden="true"></i></button>
<button class="btn btn--option btn--like">Sports apparel <i class="fa fa-check is-grey" aria-hidden="true"></i></button>
</div>

Answer

Just toggle the class on the current button first, then take the length (see comments):

$(".btn--like").on("click", function() {
  // FIRST toggle the classs
  $(this).toggleClass("is-selected");

  // THEN take the count
  let countLike = $(".btn--like.is-selected").length;
  console.log(countLike);

  $(this).children(".fa-check").toggleClass("is-grey");
  $(this).children(".fa-check").toggleClass("is-red");

  if (countLike === 3) {
    $(".btn--like:not(.is-selected)").css("pointer-events", "none");
  } else {
    $(".btn--like").css("pointer-events", "auto");
  }
});
.is-selected {
  color: blue;
}
<div class="button__group">
  <button class="btn btn--option btn--like">Jewelry <i class="fa fa-check is-grey" aria-hidden="true"></i>
  </button>
  <button class="btn btn--option btn--like">Scarves <i class="fa fa-check is-grey" aria-hidden="true"></i>
  </button>
  <button class="btn btn--option btn--like">Fishing <i class="fa fa-check is-grey" aria-hidden="true"></i>
  </button>
  <button class="btn btn--option btn--like">Cologne <i class="fa fa-check is-grey" aria-hidden="true"></i>
  </button>
  <button class="btn btn--option btn--like">Shirts <i class="fa fa-check is-grey" aria-hidden="true"></i>
  </button>
  <button class="btn btn--option btn--like">Sports apparel <i class="fa fa-check is-grey" aria-hidden="true"></i>
  </button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

FWIW, I'd probably also actually change the disabled state of the buttons rather than just disabling pointer events on them:

$(".btn--like").on("click", function() {
  // FIRST toggle the class
  $(this).toggleClass("is-selected");

  // THEN take the count
  let countLike = $(".btn--like.is-selected").length;
  console.log(countLike);

  $(this).children(".fa-check").toggleClass("is-grey");
  $(this).children(".fa-check").toggleClass("is-red");

  // Update the disabled property rather than using pointer-events
  if (countLike === 3) {
    $(".btn--like:not(.is-selected)").prop("disabled", true);
  } else {
    $(".btn--like").prop("disabled", false);
  }
});
.is-selected {
  color: blue;
}
<div class="button__group">
  <button class="btn btn--option btn--like">Jewelry <i class="fa fa-check is-grey" aria-hidden="true"></i>
  </button>
  <button class="btn btn--option btn--like">Scarves <i class="fa fa-check is-grey" aria-hidden="true"></i>
  </button>
  <button class="btn btn--option btn--like">Fishing <i class="fa fa-check is-grey" aria-hidden="true"></i>
  </button>
  <button class="btn btn--option btn--like">Cologne <i class="fa fa-check is-grey" aria-hidden="true"></i>
  </button>
  <button class="btn btn--option btn--like">Shirts <i class="fa fa-check is-grey" aria-hidden="true"></i>
  </button>
  <button class="btn btn--option btn--like">Sports apparel <i class="fa fa-check is-grey" aria-hidden="true"></i>
  </button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>