0

I have a form with school classes on it. There could be any number of classes on this form, each with 2 fields. Cost of books and cost of tuition.

I have a 3rd field called grand total which I want to update as they are typing in the costs in the other fields.

This is how I have it set up:

    $(document).on( "keyup", ".cost", function(){
        theCost = parseFloat($(this).val(), 2) || 0;
        grandTotal(theCost);
    });


    // Calculate the total
    function grandTotal(theCost){
        totalCost = (totalCost + theCost);
        console.log(totalCost);
    }

Since this runs on every keyup, if i type in 44 it just adds 4+4.

Is there a better way to do this in order to get the value of the field and not each number typed?

SBB
  • 8,560
  • 30
  • 108
  • 223
  • `parseFloat(string)` only takes one argument: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat I'm not sure that your `..., 2)` does? If you are thinking of `parseInt(string, radix)`, setting `radix=2` will convert from binary. `parseInt("110", 2) === 6` – Andreas Louv Sep 08 '14 at 20:16
  • Hm, I'm not sure why I have it like that. Maybe its the reason 33.00 + 19.98 is coming back as 52.980000000000004 – SBB Sep 08 '14 at 20:29
  • No thats because all numbers in JavaScript are double floats (IEEE 754) The same reason why `0.1 + 0.2 !== 0.3` There is a good Youtube video that explains it: https://www.youtube.com/watch?v=PZRI1IfStY0 – Andreas Louv Sep 08 '14 at 20:35

4 Answers4

1

It depends on your interface and how you want it to work.

.blur will fire when an input loses focus. You could listen for keyup or keydown and match the [Enter] key if you want to do it like that, or you could bind it to a specific button. There isn't one catch-all answer.

One other thing worth noting - you shouldn't bind events to the document in most cases. Find a sensible parent element that's not too far away from your input for it to bubble, then bind to that. A slightly better example would be $('form').on('keyup', '.cost'... so the event can be constrained to just <form>s which are relatively sparse in most pages.

Community
  • 1
  • 1
Joe
  • 15,669
  • 4
  • 48
  • 83
  • I tried on blur which would work fine I suppose- just need to figure out how to tweak the code to change based on the math. Right now if I go back and edit something, it just gives me the last total – SBB Sep 08 '14 at 20:11
  • In that case, bind the event to the form then make the handler do something like `var cost = 0; $(this).find('.cost').each(function(){ cost += parseFloat( this.val ); });` - this should recalculate the entire form you've just changed. – Joe Sep 08 '14 at 20:15
0

I would suggest iterating through the whole document of fields and re-calculating everything every time instead of trying to add a field at a time to the total cost. Any in-between method like this will result in an inaccurate total in many cases like you found, and additional quick-typing events, or edits.

BReal14
  • 1,603
  • 1
  • 12
  • 35
0

The easiest way would probably be to make theCost an array of costs for each class and then simply sum the array to get the grandTotal (a simple grandTotal = theCost.reduce(function(a, b) { return a + b; }); would work). That way it would still work with your keyup event because it would take the full numbers every time it does the calculation (so it would always take 44 instead of 4 + 4, etc).

Shomz
  • 37,421
  • 4
  • 57
  • 85
0

Many times, I see this situation handled with an Update Total button, so the action is deliberate.

$('#updateTotalButton').click(function(){
    $('.cost').each(function() {
        theCost = parseFloat($(this).val(), 2) || 0;
        grandTotal(theCost);
    });
});

// Calculate the total
function grandTotal(theCost){
    totalCost = (totalCost + theCost);
    console.log(totalCost);
}
FishBasketGordo
  • 22,904
  • 4
  • 58
  • 91