. It is all working fine " /> . It is all working fine " /> . It is all working fine "/>

Grand total not computing right in the first click of "Select All" checkbox

76 Views Asked by At

I have created a cart page. Every cart item has their own checkboxes. I use regular checkbox which is <input type="checkbox">. It is all working fine until I use iCheck plugin.

I cannot think of a better title composition of my question because it a weird circumstance.

Basically, what I want to happen is, every time I tick a checkbox, the grand_total will reflect. It works fine when I tick checkboxes until I checked all individually. grand_total reflects correctly. However, if I tick the select all checkbox for the first time, it will compute all cart_items excluding the last item in the cart. And when I click the select_all for the last time, it reflects correctly. I cannot figure out what's causing this because it works fine when I used regular checkbox. Maybe I am missing something.

Here is a quick demo of what happens: Quick Demo Video

At the first click of select_all, it seems like there are only 2 ticked checkboxes even though 3 are checked. 2 ticked checkboxes

And when I click it again there are now 3 everytime. 3 ticked checkboxes

so it seems like it happens at every first click of select all. Then works fine afterwards. And if I reload the page, there comes the problem again.

Here is my HTML code

<section class="cart_area">
    <div class="table-responsive">
        <table>
            <thead>
                <tr>
                    <th class="text-center">
                        <input type="checkbox" name="" id="" class="i-checks select_all">
                    </th>
                    <th>Product</th>
                    <th>Quantity</th>
                    <th class="text-center">Total</th>
                </tr>
            </thead>
            <tbody>
                <input type="hidden" name="cart_items" class="cart_items">
                <?php
                    $cart_items = $cakeOrdering->get_data("SELECT * FROM vw_cart_items WHERE cartID = ? ORDER BY cart_itemID DESC", array($_SESSION['cartID']));
                    if(!empty($cart_items)){
                        if(is_array($cart_items) || is_object($cart_items)){
                            foreach($cart_items as $cart_item){
                ?>
                <tr data-id="<?php echo $cart_item['cart_itemID'] ?>">
                    <td class="text-center">
                        <input type="checkbox" name="" id="" class="i-checks cart_item_checkbox">
                    </td>
                    <td class="product">
                        <img src="../img/cake_uploads/<?php echo $cart_item['image']; ?>" alt="" class="product-img">
                        <div class="prod-info">
                            <p class="prod-name"><?php echo $cart_item['prod_name'] ?></p>
                            <p class="prod-price" data-price="<?php echo $cart_item['price']; ?>">₱&nbsp;<?php echo number_format($cart_item['price'], 2, ".", ","); ?></p>
                            <a href="#" class="action text-info mr-2">Edit</a>
                            <a href="#" class="action text-danger">Delete</a>
                        </div>
                    </td>
                    <td class="quantity">
                        <div class="quantity-box">
                            <button class="minus-qty">-</button>
                            <input type="number" placeholder="1" value="<?php echo $cart_item['qty']; ?>" class="qty" disabled>
                            <button class="add-qty">+</button>
                        </div>
                    </td>
                    <td class="total text-right" data-total="<?php echo $cart_item['total_price']; ?>">₱&nbsp;<?php echo number_format($cart_item['total_price'], 2, ".", ","); ?></td>
                </tr>
                <?php }}}else{ ?>
                <tr>
                    <td colspan="4" class="text-center">There are no products in you cart. Shop now.</td>
                </tr>
                <?php } ?>
            </tbody>
        </table>
    </div>
    <div class="row mt-4">
        <div class="col-lg-7"></div>
        <div class="col-lg-5">
            <div class="cart-total-text">
                <div class="cart-head">Cart Total</div>
                <div class="total-boxes">
                    <p>Sub Total <span class="sub-total">₱ 0.00</span></p>
                </div>
                <div class="total-boxes">
                    <p>Total <span class="grand-total">₱ 0.00</span></p>
                    <input type="hidden" name="grand-total" class="grand-total">
                </div>
                <div class="cart-footer text-right">
                    <button class="btn pest_btn" id="checkout">Proceed to Checkout</button>
                </div>
            </div>
        </div>
    </div>
</section>

here is my old codes with regular checkbox: (This one works with regular checkbox)

function sum() {
    var overall_total = 0;

    $(".cart_checkbox:checked").closest("tr").find('.total_price').each(function() {
        total_price = $(this).data('total_price');
        overall_total = overall_total + parseFloat(total_price);
    })
    
    $('.overall_total').text(formatToCurrency(overall_total));
    return overall_total;
}

//   Select All
$('.select_all').on('change', function() {
    $('.cart_checkbox').not(this).prop('checked', this.checked);
    sum();
});

//   Individual Checkboxes
$(".cart_checkbox").change(function() {
    var total_length = $(".cart_checkbox").length;
    var checked_length = $(".cart_checkbox:checked").length
    //check if length less then total
    if (checked_length < total_length) {
        $('.select_all').prop('checked', false); //uncheck
    } else {
        $('.select_all').prop('checked', true); //check
    }

    sum();                  
});

And Here's my code with iCheck: (When I convert codes into iCheck, this problem occurs)

//   Select All
$(".select_all").on("ifClicked", function () {
    $(".select_all").on("ifChecked ifUnchecked", function (e) {
        if (e.type == "ifChecked") {
        $(".cart_item_checkbox").iCheck("check");
        } else {
        $(".cart_item_checkbox").iCheck("uncheck");
        }
    });
    sum();
});

//   Individual Checkboxes
$(".cart_item_checkbox").on("ifChanged", function () {
    var total_length = $(".cart_item_checkbox").length;
    var checked_length = $(".cart_item_checkbox").filter(":checked").length;

    if (checked_length < total_length) {
        $(".select_all").iCheck("uncheck");
    } else {
        $(".select_all").iCheck("check");
    }
    sum();
});

function sum() {
    var grand_total = 0;
    $(".cart_item_checkbox:checked")
        .closest("tr")
        .find(".total")
        .each(function () {
        total = $(this).data("total");
        grand_total = grand_total + parseFloat(total);
        });

    $(".sub-total").text(formatToCurrency(grand_total));
    $(".grand-total").text(formatToCurrency(grand_total));
    $(":input.grand-total").val(grand_total);
    return grand_total;
}
1

There are 1 best solutions below

2
Swati On BEST ANSWER

To make this work i have use $(this).closest("div").hasClass("checked") this will check if the parent of the checkbox has checked class or not because the iCheck plugin adds this class dynamically . Then , i have pass different selector depending on which event handler has called the sum() function.

Demo Code :

$(document).ready(function() {
  $('input').iCheck({
    checkboxClass: 'icheckbox_square-blue',
    increaseArea: '20%',
    handle: 'checkbox'
  });
})

//keep only clicked..event
$(".select_all").on("ifClicked", function(e) {
  //reverse cndtion..
  if (!$(this).closest("div").hasClass("checked")) {
    $(".cart_item_checkbox").iCheck("check");
  } else {
    $(".cart_item_checkbox").iCheck("uncheck");
  }
  sum($(".cart_item_checkbox").parent(".checked")); //pass the slector 
});


$(".cart_item_checkbox").on("ifChanged", function() {
  var total_length = $(".cart_item_checkbox").length;
  var checked_length = $(".cart_item_checkbox").filter(":checked").length;

  if (checked_length < total_length) {
    $(".select_all").iCheck("uncheck");
  } else {
    $(".select_all").iCheck("check");

  }
  sum($(".cart_item_checkbox:checked")); //here pass different selector
});

function sum(el) {
  var grand_total = 0;
  el.closest("tr")
    .find(".total")
    .each(function() {
      total = $(this).data("total");
      grand_total = grand_total + parseFloat(total);
    });

  //remove formatToCurrency..for demo..purpose.
  $(".sub-total").text((grand_total));
  $(".grand-total").text((grand_total));
  $(":input.grand-total").val(grand_total);
  return grand_total;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/iCheck/1.0.3/skins/all.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/iCheck/1.0.3/icheck.min.js"></script>
<section class="cart_area">
  <div class="table-responsive">
    <table>
      <thead>
        <tr>
          <th class="text-center">
            <input type="checkbox" name="" id="" class="i-checks select_all">
          </th>
          <th>Product</th>
          <th>Quantity</th>
          <th class="text-center">Total</th>
        </tr>
      </thead>
      <tbody>
        <input type="hidden" name="cart_items" class="cart_items">


        <tr data-id="1">
          <td class="text-center">
            <input type="checkbox" name="" id="" class=" cart_item_checkbox">
          </td>
          <td class="product">
            <img src="../img/cake_uploads/<?php echo $cart_item['image']; ?>" alt="" class="product-img">
            <div class="prod-info">
              <p class="prod-name">
                A
              </p>
              <p class="prod-price" data-price="12">₱&nbsp; 12
              </p>
              <a href="#" class="action text-info mr-2">Edit</a>
              <a href="#" class="action text-danger">Delete</a>
            </div>
          </td>
          <td class="quantity">
            <div class="quantity-box">
              <button class="minus-qty">-</button>
              <input type="number" placeholder="1" value="2" class="qty" disabled>
              <button class="add-qty">+</button>
            </div>
          </td>
          <td class="total text-right" data-total="24">₱&nbsp; 24
          </td>
        </tr>
        <tr data-id="2">
          <td class="text-center">
            <input type="checkbox" name="" id="" class="i-checks cart_item_checkbox">
          </td>
          <td class="product">
            <img src="../img/cake_uploads/<?php echo $cart_item['image']; ?>" alt="" class="product-img">
            <div class="prod-info">
              <p class="prod-name">
                A
              </p>
              <p class="prod-price" data-price="12">₱&nbsp; 12
              </p>
              <a href="#" class="action text-info mr-2">Edit</a>
              <a href="#" class="action text-danger">Delete</a>
            </div>
          </td>
          <td class="quantity">
            <div class="quantity-box">
              <button class="minus-qty">-</button>
              <input type="number" placeholder="1" value="3" class="qty" disabled>
              <button class="add-qty">+</button>
            </div>
          </td>
          <td class="total text-right" data-total="36">₱&nbsp; 36
          </td>
        </tr>
      </tbody>
    </table>
  </div>
  <div class="row mt-4">
    <div class="col-lg-7"></div>
    <div class="col-lg-5">
      <div class="cart-total-text">
        <div class="cart-head">Cart Total</div>
        <div class="total-boxes">
          <p>Sub Total <span class="sub-total">₱ 0.00</span></p>
        </div>
        <div class="total-boxes">
          <p>Total <span class="grand-total">₱ 0.00</span></p>
          <input type="hidden" name="grand-total" class="grand-total">
        </div>
        <div class="cart-footer text-right">
          <button class="btn pest_btn" id="checkout">Proceed to Checkout</button>
        </div>
      </div>
    </div>
  </div>
</section>