General total does not sum

Asked

Viewed 57 times

0

I am putting together this budget form. Almost everything is perfect. Just the total sum, which however fit is not adding up.

$(".real").maskMoney({
  prefix: 'R$ ',
  thousands: '.',
  decimal: ',',
  affixesStay: true
});



function rePlace(i) {
  return parseFloat(i.replace(/[^\d.,]/g, "").replace('.', '').replace(',', '.'));
}

Number.prototype.formataReal = function(c, d, t) {
  var n = this,
    c = isNaN(c = Math.abs(c)) ? 2 : c,
    d = d == undefined ? "," : d,
    t = t == undefined ? "." : t,
    s = n < 0 ? "-" : "",
    i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "",
    j = (j = i.length) > 3 ? j % 3 : 0;
  return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};
//any time the amount changes
$(document).ready(function() {
  $('input[name=r],input[name=p]').change(function(e) {
    var total = 0;
    var $row = $(this).parent();
    var rate = rePlace($row.find('.r').val());
    var pack = $row.find('.p').val();
    total = parseFloat(rate * pack);
    //update the row total
    $row.find('.amount').val('R$ ' + (total).formataReal(2, ',', '.'));

    var total_amount = 0;
    $('.amount').each(function() {
      //Get the value
      var am = rePlace($(this).val());
      console.log(am);
      //if it's a number add it to the total
      if (IsNumeric(am)) {
        total_amount += parseFloat(am);
      }
    });
    $('.total_amount').val(total_amount);
  });
});

function IsNumeric(input) {
  return (input - 0) == input && input.length > 0;
}
<script src="https://blackrockdigital.github.io/startbootstrap-sb-admin-2/vendor/jquery/jquery.min.js"></script>
<script type="text/javascript" src="https://plentz.github.io/jquery-maskmoney/javascripts/jquery.maskMoney.min.js"></script>

<div>
  <input name="r" class="rate r real" type="text" value="" />
  <input name="p" class="pack p" type="text" value="" />
  <input class="amount" type="text" value="" />
</div>
<div>
  <input name="r" class="rate r real" type="text" value="" />
  <input name="p" class="pack p" type="text" value="" />
  <input class="amount" type="text" value="" />
</div>
<div>
  <input name="r" class="rate r real" type="text" value="" />
  <input name="p" class="pack p" type="text" value="" />
  <input class="amount" type="text" value="" />
</div>
<input class="total_amount" type="text" value="" />

1 answer

1

The problem lies in its numerical checking function IsNumeric:

function IsNumeric(input) {
  return (input - 0) == input && input.length > 0;
}

The .length about a Number will give undefined and so the comparison will always be false.

Change your job function IsNumeric for:

function isNumeric(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

I used the validation function as a reference of this question in Soen.

Analyzing it we see that the isNaN returns if it is not a number. So we start by testing the inverse !isNaN to see if it is a number. However, it also uses the isFinite to be able to make specific inputs such as 1/0 who give infinity do not pass the test.

See this example on the isFinite:

console.log(1/0)
console.log(isFinite(1/0));

See how your code already works with this change:

$(".real").maskMoney({
  prefix: 'R$ ',
  thousands: '.',
  decimal: ',',
  affixesStay: true
});



function rePlace(i) {
  return parseFloat(i.replace(/[^\d.,]/g, "").replace('.', '').replace(',', '.'));
}

Number.prototype.formataReal = function(c, d, t) {
  var n = this,
    c = isNaN(c = Math.abs(c)) ? 2 : c,
    d = d == undefined ? "," : d,
    t = t == undefined ? "." : t,
    s = n < 0 ? "-" : "",
    i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "",
    j = (j = i.length) > 3 ? j % 3 : 0;
  return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};
//any time the amount changes
$(document).ready(function() {
  $('input[name=r],input[name=p]').change(function(e) {
    var total = 0;
    var $row = $(this).parent();
    var rate = rePlace($row.find('.r').val());
    var pack = $row.find('.p').val();
    total = parseFloat(rate * pack);
    //update the row total
    $row.find('.amount').val('R$ ' + (total).formataReal(2, ',', '.'));

    var total_amount = 0;
    $('.amount').each(function() {
      //Get the value
      var am = rePlace($(this).val());
      //console.log(am);
      //if it's a number add it to the total
      if (IsNumeric(am)) {
        total_amount += parseFloat(am);
      }
    });
    $('.total_amount').val(total_amount);
  });
});

function IsNumeric(input) {
  return !isNaN(parseFloat(input)) && isFinite(input);
}
<script src="https://blackrockdigital.github.io/startbootstrap-sb-admin-2/vendor/jquery/jquery.min.js"></script>
<script type="text/javascript" src="https://plentz.github.io/jquery-maskmoney/javascripts/jquery.maskMoney.min.js"></script>

<div>
  <input name="r" class="rate r real" type="text" value="" />
  <input name="p" class="pack p" type="text" value="" />
  <input class="amount" type="text" value="" />
</div>
<div>
  <input name="r" class="rate r real" type="text" value="" />
  <input name="p" class="pack p" type="text" value="" />
  <input class="amount" type="text" value="" />
</div>
<div>
  <input name="r" class="rate r real" type="text" value="" />
  <input name="p" class="pack p" type="text" value="" />
  <input class="amount" type="text" value="" />
</div>
<input class="total_amount" type="text" value="" />

  • I forgot and now that I went to close the screen I came across the situation: the customer can change the total amount. Even if I change the $('. value_total_orc'). each(Function() for change, does not remake the calculation. It would be possible to recalculate the general value after changing the value of the line?

  • @Rogériopancini But if the total is calculated and not indicated by the customer then it will make more sense to make it readonly which simultaneously solves the problem

Browser other questions tagged

You are not signed in. Login or sign up in order to post.