Search code examples
javascriptjqueryonclickstring-length

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>

Solution

  • 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>