Grand total does not add

0

I am putting together this budget form. Almost everything is perfect. Only the sum total, which by whatever adjustment 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><scripttype="text/javascript" src="https://plentz.github.io/jquery-maskmoney/javascripts/jquery.maskMoney.min.js"></script><div><inputname="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="" />
    
asked by anonymous 19.02.2018 / 20:04

1 answer

1

The problem is in its function of checking numeric IsNumeric :

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

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

Change your function IsNumeric to:

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

I used the validation function reference in SOen as a reference.

Looking at it we see that isNaN returns if it is not a number. So we start by testing the inverse !isNaN to see if it is a number. However, you also use isFinite to get inputs specifics such as 1/0 that give infinity do not pass the test.

See this example on 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><scripttype="text/javascript" src="https://plentz.github.io/jquery-maskmoney/javascripts/jquery.maskMoney.min.js"></script><div><inputname="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="" />
    
19.02.2018 / 20:52