javascript - Calculate on change for each row - Stack Overflow

I have an invoice form to generate a PDF. I want to calculate the inputs after the change of the value

I have an invoice form to generate a PDF. I want to calculate the inputs after the change of the value that the user fills in the form.

I can calculate the first row, but i want to (1) calculate each row and at the end to (2) calculate all the colums properly. For the first step just to the (1) and i will make the total calculation.

The problem is that i generate the rows with dynamic name and id because i post them in an array to the database. For this example the id is the same for every row of inputs.

PS: i cannot make .change work and i use $(document).on('change', '#qty', function (e) { calculateLine(); }); to trigger the calculation function for each input. I dont know why .change is not working as it support to, with latest jquery.

[invoice.php]

<script>
    $(document).ready(function () {

        $(document).on('change', '#qty', function (e) { calculateLine(); });
        $(document).on('change', '#price', function (e) { calculateLine(); });
        $(document).on('change', '#discount', function (e) { calculateLine(); });
        $(document).on('change', '#discountPrice', function (e) { calculateLine(); });

    });
</script>

[invoice.js]

function calculateLine() {

    var qty = parseFloat($('#qty').val());
    var price = parseFloat($('#price').val());
    var discount = parseFloat($('#discount').val());
    var discountPrice = parseFloat($('#discountPrice').val());
    var vat = parseFloat($('#vat').val());

    var netTotal = 0;
    var total = 0;
    var vatAmount = 0;

    if (!qty && qty == 0) {
        return;
    }
    if (!price && price == 0) {
        return;
    }

    netTotal = qty * price;

    if ((!discount || discount == 0) && discountPrice != 0) {
        discount = (discountPrice / netTotal) * 100;
    }
    if ((!discountPrice || discountPrice == 0) && discount != 0) {
        discountPrice = (netTotal / 100) * discount;
    }
    if (discountPrice != 0 && discount != 0) {
        discountPrice = (netTotal / 100) * discount;
    }
    if ((!discount || discount == 0) && (!discountPrice || discountPrice == 0)) {
        discountPrice = 0;
        discount = 0;
    }

    total = netTotal - discountPrice;

    if (!total || total == 0) {
        total = 0;
    }
    vatAmount = (total / 100) * vat;

    $('#total').val(total);
    $('#discount').val(discount);
    $('#discountPrice').val(discountPrice);
    $('#vatAmount').val(vatAmount);

    //calculateTotal();
}

[html]

<tr>
    <td class="col-xs-0">
        <input type="checkbox" name="selected[]" class="checkall">
    </td>
    <td class="col-xs-5">
        <textarea type="text" name="invoice[item][{{j}}][description]" class="form-control description" rows="1" ></textarea>
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][unit]" class="form-control unit" value="" />
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][qty]" class="form-control qty" value="" />
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][price]" class="form-control price" value="" />
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][discount]" class="form-control discount" value="" >
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][discountPrice]" class="form-control discountPrice" />
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][total]" class="form-control total" value="" />
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][vat]" class="form-control vat" value="{{invcl_vat}}" readonly />
        <input type="hidden" name="invoice[item][{{j}}][vatAmount]" class="form-control vatAmount" value="" readonly />
    </td>
</tr>

I have an invoice form to generate a PDF. I want to calculate the inputs after the change of the value that the user fills in the form.

I can calculate the first row, but i want to (1) calculate each row and at the end to (2) calculate all the colums properly. For the first step just to the (1) and i will make the total calculation.

The problem is that i generate the rows with dynamic name and id because i post them in an array to the database. For this example the id is the same for every row of inputs.

PS: i cannot make .change work and i use $(document).on('change', '#qty', function (e) { calculateLine(); }); to trigger the calculation function for each input. I dont know why .change is not working as it support to, with latest jquery.

[invoice.php]

<script>
    $(document).ready(function () {

        $(document).on('change', '#qty', function (e) { calculateLine(); });
        $(document).on('change', '#price', function (e) { calculateLine(); });
        $(document).on('change', '#discount', function (e) { calculateLine(); });
        $(document).on('change', '#discountPrice', function (e) { calculateLine(); });

    });
</script>

[invoice.js]

function calculateLine() {

    var qty = parseFloat($('#qty').val());
    var price = parseFloat($('#price').val());
    var discount = parseFloat($('#discount').val());
    var discountPrice = parseFloat($('#discountPrice').val());
    var vat = parseFloat($('#vat').val());

    var netTotal = 0;
    var total = 0;
    var vatAmount = 0;

    if (!qty && qty == 0) {
        return;
    }
    if (!price && price == 0) {
        return;
    }

    netTotal = qty * price;

    if ((!discount || discount == 0) && discountPrice != 0) {
        discount = (discountPrice / netTotal) * 100;
    }
    if ((!discountPrice || discountPrice == 0) && discount != 0) {
        discountPrice = (netTotal / 100) * discount;
    }
    if (discountPrice != 0 && discount != 0) {
        discountPrice = (netTotal / 100) * discount;
    }
    if ((!discount || discount == 0) && (!discountPrice || discountPrice == 0)) {
        discountPrice = 0;
        discount = 0;
    }

    total = netTotal - discountPrice;

    if (!total || total == 0) {
        total = 0;
    }
    vatAmount = (total / 100) * vat;

    $('#total').val(total);
    $('#discount').val(discount);
    $('#discountPrice').val(discountPrice);
    $('#vatAmount').val(vatAmount);

    //calculateTotal();
}

[html]

<tr>
    <td class="col-xs-0">
        <input type="checkbox" name="selected[]" class="checkall">
    </td>
    <td class="col-xs-5">
        <textarea type="text" name="invoice[item][{{j}}][description]" class="form-control description" rows="1" ></textarea>
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][unit]" class="form-control unit" value="" />
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][qty]" class="form-control qty" value="" />
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][price]" class="form-control price" value="" />
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][discount]" class="form-control discount" value="" >
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][discountPrice]" class="form-control discountPrice" />
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][total]" class="form-control total" value="" />
    </td>
    <td class="col-xs-1">
        <input type="text" name="invoice[item][{{j}}][vat]" class="form-control vat" value="{{invcl_vat}}" readonly />
        <input type="hidden" name="invoice[item][{{j}}][vatAmount]" class="form-control vatAmount" value="" readonly />
    </td>
</tr>
Share Improve this question edited Jul 9, 2014 at 7:48 John Priestakos asked Jul 9, 2014 at 7:07 John PriestakosJohn Priestakos 3905 silver badges19 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 6

You haven't shown your HTML, but it's clear from your question that you're using the same id (qty, etc.) on more than one element. You can't do that. Every id must be unique on the page. In this case, you'd probably use classes instead.

The general way that you do what you're talking about is indeed to use delegated event handling, then find the containing row, and use that as the starting point looking for descendant inputs using classes rather than ids:

$("selector-for-the-table").on("change", "input", function() {
    // Get the row containing the input
    var row = $(this).closest("tr");

    // Get the values from _this row's_ inputs, using `row.find` to
    // look only within this row
    var qty = parseFloat(row.find('.qty').val());
    var price = parseFloat(row.find('.price').val());
    var discount = parseFloat(row.find('.discount').val());
    var discountPrice = parseFloat(row.find('.discountPrice').val());
    var vat = parseFloat(row.find('.vat').val());

    // ...
});

I've also rooted that on the table, rather than document, so it only applies where appropriate.

Live (Simplified) Example:

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery./jquery-1.11.0.min.js"></script>
  <meta charset="utf-8">
  <title>Example</title>
</head>
<body>
  <table>
    <thead>
      <tr>
        <th>Quantity</th>
        <th>Price</th>
        <th>Total</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><input type="text" class="qty"></td>
        <td><input type="text" class="price"></td>
        <td><input type="text" class="total" disabled></td>
      </tr>
      <!-- ...and so on... -->
    </tbody>
  </table>
<script>
  (function() {
    "use strict";

    $("table").on("change", "input", function() {
      var row = $(this).closest("tr");
      var qty = parseFloat(row.find(".qty").val());
      var price = parseFloat(row.find(".price").val());
      var total = qty * price;
      row.find(".total").val(isNaN(total) ? "" : total);
    });
  })();
</script>
</body>
</html>

You've said before that the names are dynamic. Surely there is some characteristic of the fields you're trying to find that is consistent, or you can make them consistent. In the worst case (and I mean in the worst case), you could do something based on position — the first input in the row is row.find("input:eq(0)"), the second is row.find("input:eq(1)"), and so on.

Live Example Using eq:

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery./jquery-1.11.0.min.js"></script>
  <meta charset="utf-8">
  <title>Example</title>
</head>
<body>
  <table>
    <thead>
      <tr>
        <th>Quantity</th>
        <th>Price</th>
        <th>Total</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><input type="text"></td>
        <td><input type="text"></td>
        <td><input type="text" disabled></td>
      </tr>
      <!-- ...and so on... -->
    </tbody>
  </table>
<script>
  (function() {
    "use strict";

    $("table").on("change", "input", function() {
      var row = $(this).closest("tr");
      var qty = parseFloat(row.find("input:eq(0)").val());
      var price = parseFloat(row.find("input:eq(1)").val());
      var total = qty * price;
      row.find("input:eq(2)").val(isNaN(total) ? "" : total);
    });
  })();
</script>
</body>
</html>

But avoid that if you possibly can, it's fragile — if you change the order of columns, you have to change your code.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742382681a4433431.html

相关推荐

  • javascript - Calculate on change for each row - Stack Overflow

    I have an invoice form to generate a PDF. I want to calculate the inputs after the change of the value

    18小时前
    10

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信