How do I access only specific elements that have a same class? jquery

I am trying to create a shopping cart-like function that displays products found in a database and the user can select the quantity of each product and then add it to a cart. The problem that I am currently facing is that when the user clicks on a plus button, all the quantities change and they all display the clicked total price. This is the code I have :

$('.plus').bind('click', function(e) {
  $('.minus').prop('disabled', false)

  var quantity = parseInt($('.quantity').val());
  if (!isNaN(quantity) && quantity < 8) {
    $('.quantity').val(quantity + 1);
  } else if (quantity == 8) {
    $('.quantity').val(9);
    $(this).prop('disabled', true)
  }
  var price = parseFloat($('.price').text()).toFixed(2);

  if (quantity != 9) {
    if ((price * quantity) % 1 !== 0) {
      $(".total_price").val(parseFloat(price * (quantity + 1)) + ".00");
    } else {
      $(".total_price").val(parseFloat(price * (quantity + 1)) + "0");
    }
    $(".total_price").css("font-weight", "Bold");
    $(".total_price").css("color", "brown");
  } else {
    if ((price * quantity) % 1 !== 0) {
      $(".total_price").val(parseFloat(price * 9) + ".00");
    } else {
      $(".total_price").val(parseFloat(price * 9) + "0");
    }
    $(".total_price").css("font-weight", "Bold");
    $(".total_price").css("color", "brown");
  }
});

$('.minus').bind('click', function(e) {
  $('.plus').prop('disabled', false)

  var quantity = parseInt($('.quantity').val());
  if (!isNaN(quantity) && quantity > 1) {
    $('.quantity').val(quantity - 1);
  } else {
    $(this).prop('disabled', true)
    $('.quantity').val(0);

  }
  var price = parseFloat($('.price').text()).toFixed(2);
  if ((price * quantity) % 1 !== 0) {
    $(".total_price").val(parseFloat(price * (quantity - 1)) + ".00");
  } else {
    $(".total_price").val(parseFloat(price * (quantity - 1)) + "0");
  }

  if (quantity != 1) {
    $(".total_price").css("font-weight", "Bold");
    $(".total_price").css("color", "brown");
  } else {

    $(".total_price").css("font-weight", "normal");
    $(".total_price").css("color", "black");
  }


});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='row' id='product_item'>
  <div class='col-5' style='margin: auto;'>
    <input class='product_name' readonly type='text' name='product_name' style='display: inline; width:100%; border:white;' value='".$row[' productName ']."'>
  </div>
  <div class='col-1' style='margin: auto;'>
    <div class='price' style='display: inline;'>".$row['price']."</div>€</div>

  <div class='col-3' style='display:inline;  margin: auto;'>
    <div class='input_group_button'>
      <button class='btn plus' type='button'>
           <img src='img/plus.png'>
       </button>
    </div>
    <input class='input_group_field quantity' readonly type='number' name='quantity' value='0' max=9>
    <div class='input_group_button'>
      <button class='btn minus' type='button'>
         <img src='img/minus.png'>
      </button>
    </div>
  </div>
  <div class='col-2' style='margin: auto;'><input class='total_price' readonly type='number' name='total_price' style='display: inline; width:65%; border:white;' value='0.00'>€</div>
  <div class='col-1'>
    <button class='btn' type='button' id='add_cart'>
     <img src='img/add-to-cart.png'>
    </button>
  </div>
</div>

I appreciate any help I can get!

Answer

To make this work you can use the reference to the clicked element, using the this keyword in the event handler, to traverse the DOM to find the related elements using jQuery’s built in methods such as closest() and find().

In addition there’s a couple of other things which can be addressed.

  • bind() has been deprecated. Use on() instead.
  • You can combine the .minus and .plus event handlers by using a data attribute on the buttons to determine which value should be added to the quantity. This reduces the amount of repetition in the code.
  • You can use Math.max() and Math.min() to set the extents of the quantity field. This makes the code more succinct by removing the need for the lengthy if condition.
  • Do not use id attributes in content which is repeated throughout the page. id have to be unique within the DOM. Use class attributes instead to group elements by behaviour.
  • It’s odd to use a block level div element and force it to be inline. If you want an inline element use on directly, such as a span.
  • Avoid putting styling rules in your HTML. Put them in an external stylesheet.

With all that said, try this:

$('.btn-inc').on('click', function(e) {
  let $el = $(this);
  let inc = $el.data('inc');
  $el.closest('.col-3').find('.quantity').val((i, v) => Math.min(Math.max(parseInt(v, 10) + inc, 0), 8));
  updatePrice();
});

let updatePrice = () => {
  $('.row').each((i, row) => {
    let $row = $(row);
    let $price = $row.find('.price');
    let $quantity = $row.find('.quantity');

    $row.find('.total_price').val(parseFloat($price.text() * $quantity.val()).toFixed(2));
  });
}
.row {
  border: 1px solid #CCC;
  border-radius: 5px;
  margin: 10px;
  padding: 10px;
} 
.row > div margin: auto;

}
.row > .col-3 {
  display: inline;
}
input.product_name {
  display: inline;
  width: 100%;
  border: white;
}
input.total_price {
  display: inline;
  width: 65%;
  border: white;
}
span.price {
  display: inline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!-- item 1 -->
<div class="row">
  <div class="col-5">
    <input class="product_name" readonly type="text" name="product_name" value="productName">
  </div>
  <div class="col-1">
    <span class="price">1.00</span>€
  </div>
  <div class="col-3">
    <div class="input_group_button">
      <button class="btn plus btn-inc" type="button" data-inc="1">+</button>
    </div>
    <input class="input_group_field quantity" readonly type="number" name="quantity" value="0" max="9">
    <div class="input_group_button">
      <button class="btn minus btn-inc" type="button" data-inc="-1">-</button>
    </div>
  </div>
  <div class="col-2">
    <input class="total_price" readonly type="number" name="total_price" value="0.00"> €
  </div>
  <div class="col-1">
    <button class="btn" type="button" class="add_cart">Add to cart</button>
  </div>
</div>

<!-- item 2 -->
<div class="row">
  <div class="col-5">
    <input class="product_name" readonly type="text" name="product_name" value="productName">
  </div>
  <div class="col-1">
    <span class="price">9.99</span>€
  </div>
  <div class="col-3">
    <div class="input_group_button">
      <button class="btn plus btn-inc" type="button" data-inc="1">+</button>
    </div>
    <input class="input_group_field quantity" readonly type="number" name="quantity" value="0" max="9">
    <div class="input_group_button">
      <button class="btn minus btn-inc" type="button" data-inc="-1">-</button>
    </div>
  </div>
  <div class="col-2">
    <input class="total_price" readonly type="number" name="total_price" value="0.00"> €
  </div>
  <div class="col-1">
    <button class="btn" type="button" class="add_cart">Add to cart</button>
  </div>
</div>

Leave a Reply

Your email address will not be published. Required fields are marked *