2

I am fairly new to Javascript, and working with the DOM. I'm trying to add the user's input values to a total. Every time they add a value for credit or debit, it will add it to the total. Every attempt I've made, results in NaN, undefined or some other error. Do I need a for loop or is there a simpler way to do this?

Here is the full code: JSFiddle

My Javascript snippet (to add totals):

if (document.getElementsByTagName('select')[0].selectedIndex == 1) {
transactions.appendChild(debit);
text = document.createTextNode("debit");
td2.appendChild(text);

var money = document.querySelector('input[type="number"]').value;
money = parseFloat(money).toFixed(2);
var total = 0;

for (var i = 0; i < money.length; i++) {
  if (parseInt(money[i].value))
    total += parseInt(money[i].value);
}

document.querySelector('.right > .total.debits').innerHTML = total;

evt.target.reset();

}

My HTML:

<body>
<section class="wrapper">
    <h1>Transaction Tracker</h1>
    <form class="transaction-frm">
        <fieldset>
            <legend>Add Transaction</legend>
            <div class="frm-group">
                <input class="frm-control" type="text" name="description" size="30" placeholder="description" />
            </div>
            <div class="frm-group">
                <select class="frm-control" name="type">
                    <option value="">type</option>
                    <option value="debit">debit</option>
                    <option value="credit">credit</option>
                </select>
            </div>
            <div class="frm-group">
                <i class="edit fa fa-dollar"></i>
                <input class="frm-control" type="number" name="currency" min="0" max="9999" step="0.01" size="4" placeholder="0.00" />
            </div>
            <div class="frm-group">
                <input class="frm-control" type="submit" value="add" />
            </div>
            <div class="error"></div>
        </fieldset>
    </form>


    <h2>Transactions</h2>


    <table class="transactions">
        <thead>
            <tr>
                <td colspan="4" class="right">
                    Total debits: <span class="total debits">$0.00</span>
                    Total credits: <span class="total credits">$0.00</span>
                </td>
            </tr>
            <tr>
                <th>Description</th>
                <th>Type</th>
                <th class="amount">Amount</th>
                <th class="tools">Tools</th>
            </tr>
        </thead>
        <tbody>

        </tbody>
    </table>
</section>
<script src="js/main.js"></script>

4 Answers4

2

This should work if you replace your current JSFiddle script with this. It takes the current value in the span and removes the $ then adds to it. Then to make it look nice it makes it a fixed length after the decimal and prepends a dollar sign. And finally updates the span value to the new total. This will need modification if you plan to be able to delete nodes. If you did implement deleting you would read the node type and value and minus instead of add.

document.querySelector('form').addEventListener('submit', function(evt) {

  var transactions = document.querySelector('tbody');
  var debit, credit, moneyText, descriptionText,
    error, td, td2, td3, td4, td5, td6, td7, td8, i, i2;

  description = document.querySelector('input[type="text"]').value;
      money = document.querySelector('input[type="number"]').value;
      money = parseFloat(money).toFixed(2);


  if (document.getElementsByTagName('select')[0].selectedIndex == 0) {
    alert("Please select a payment option");
    document.getElementsByTagName('select')[0].focus();
  }
  if (document.querySelector('input[type="text"]').value == "") {
    alert("Please enter a description");
    document.querySelector('input[type="text"]').focus();
  }

  if (document.querySelector('input[type="number"]').value < 0 || document.querySelector('input[type="number"]').value == "") {
    alert("Please enter a number over 0");
    document.querySelector('input[type="number"]').focus();
  }

  debit = document.createElement('tr');
  credit = document.createElement('tr');
  debitDescriptionText = document.createTextNode(description);
  debitMoneyText = document.createTextNode(money);
  creditDescriptionText = document.createTextNode(description);
  creditMoneyText = document.createTextNode(money);

  td = document.createElement('td');
  td2 = document.createElement('td');
  td3 = document.createElement('td');
  td4 = document.createElement('td');

  td5 = document.createElement('td');
  td6 = document.createElement('td');
  td7 = document.createElement('td');
  td8 = document.createElement('td');

  i = document.createElement('i');
  i2 = document.createElement('i');

  debit.setAttribute('class', 'debit');
  credit.setAttribute('class', 'credit');
  td3.setAttribute('class', 'amount');
  td4.setAttribute('class', 'tools');
  td7.setAttribute('class', 'amount');
  td8.setAttribute('class', 'tools');

  i.setAttribute('class', 'delete fa fa-trash-o');
  i2.setAttribute('class', 'delete fa fa-trash-o');

  sign = document.createTextNode("$");
  td3.appendChild(sign);

  sign = document.createTextNode("$");
  td7.appendChild(sign);

  debit.appendChild(td);
  debit.appendChild(td2);
  debit.appendChild(td3);
  debit.appendChild(td4);
  td.appendChild(debitDescriptionText);
  td3.appendChild(debitMoneyText);
  td5.appendChild(creditDescriptionText);
  td7.appendChild(creditMoneyText);

  td4.appendChild(i);
  credit.appendChild(td5);
  credit.appendChild(td6);
  credit.appendChild(td7);
  credit.appendChild(td8);
  td8.appendChild(i2);


  if (document.getElementsByTagName('select')[0].selectedIndex == 1) {
    transactions.appendChild(debit);
    text = document.createTextNode("debit");
    td2.appendChild(text);

    var money = document.querySelector('input[type="number"]').value;


    document.querySelector('.right > .total.debits').innerHTML ="$"+(parseInt(document.querySelector('.right > .total.debits').innerText.replace("$",""))+parseFloat(money)).toFixed(2);

    evt.target.reset();
  }

  if (document.getElementsByTagName('select')[0].selectedIndex == 2) {
    transactions.appendChild(credit);
    text = document.createTextNode("credit");
    td6.appendChild(text);

    var money = document.querySelector('input[type="number"]').value;


    document.querySelector('.right > .total.credits').innerHTML ="$"+(parseInt(document.querySelector('.right > .total.credits').innerText.replace("$",""))+parseFloat(money)).toFixed(2);


    evt.target.reset();
  }

  evt.preventDefault();

});

document.querySelector('.transactions').addEventListener('click', function(evt) {
  // check for click on an arrow
  var target = evt.target.parentNode;
  var trash = target.parentNode;

  if (evt.target.classList.contains('delete')) {
    trash.remove(target);
  }
});
C L K Kissane
  • 34
  • 1
  • 5
1

You need to declare total variables outside of your event.

`var debitTotal = 0.0, creditTotal = 0.0;`

you are also converting too many times when trying to get the total it's unnecessary, you can just add floats. Remove the .toFixed(2) from money = parseFloat(money).toFixed(2). toFixed(2) turns your value into a string. Also remove the for loop. All you need is:

var money = document.querySelector('input[type="number"]').value;
money = parseFloat(money);
debitTotal += money;

to get your total. Then to display the total you can add .toFixed(2);

document.querySelector('.right > .total.debits').innerHTML = '$' + debitTotal.toFixed(2);

I did basically the same thing for credits.

Here is the updated jsfiddle.

Anthony
  • 1,439
  • 1
  • 19
  • 36
0

I checked the fiddle you made, and the transactions listing doesn't seem to throw any errors as long as the form field are filled properly.

The validation checks you added to the fields need a return statement after it resolves as invalid.

The problem is if no data is entered, the value is being resolved as NaN and you are adding adding a row for it even after displaying the alert saying it is invalid. (Since the function does not exit even if input values are invalid)

Arun Iyer
  • 54
  • 2
  • 5
0
money = parseFloat(money).toFixed(2);

typeof money -> number with 2 characters after the decimal point

var total = 0;

for (var i = 0; i < money.length; i++) {

money becomes string and you check every character

  if (parseInt(money[i].value))

money[i](string variable).value is undefined, so parseInt(undefined) = NaN -means Not a Number

    total += parseInt(money[i].value);
}

so you don' need loop, just

total += parseInt(money)
Alexey G
  • 1,068
  • 1
  • 14
  • 18