0

I've got a JS script I found at http://css-tricks.com/multi-product-quantity-based-order-form/

Once I've implemented it, the multiplication is incorrect. Here is the page I'm working on: http://www.trueliteinc.com/index.php/carrabbas-order-form/

If you put "15" as the quantity for the second item down, the total is $38.8499999 instead of $38.85. Why? How can I fix this problem?

This is the function I believe is doing the multiplying:

function calcTotalPallets() {

var totalPallets = 0;

$(".num-pallets-input").each(function() {

    var thisValue = parseFloat($(this).val());

    if ( (IsNumeric(thisValue)) &&  (thisValue != '') ) {
        totalPallets += parseInt(thisValue);
    };

});

$("#total-pallets-input").val(totalPallets).toFixed(2);

}

My entire code can be found at http://jsfiddle.net/2aFCs/3/

Thanks so much in advance

Tara
  • 251
  • 1
  • 5
  • 17
  • 1
    A nice work around is to work in cents when doing computations and divide by 100 when displaying to the user. Not exactly a "solution" to your problem, but more of advice to avoid headaches like these. – isick Jan 10 '14 at 16:53
  • Can you at least make your fiddle work so it replicates your problem? – MikeSmithDev Jan 10 '14 at 16:53
  • A nice solution is having an object with `whole` and `cents`, and a method that takes a **string**, and does the necessary calculations on **integers**, then `toString` gives you the representation of that, as `whole.cents` – elclanrs Jan 10 '14 at 17:00
  • @MikeSmithDev done! http://jsfiddle.net/2aFCs/3/ – Tara Jan 10 '14 at 17:00
  • @elclanrs thank you for the comment. Unfortunately, my background in Javascript is limited, so I'm not entirely sure how to do that. – Tara Jan 10 '14 at 17:06

3 Answers3

2

You are calling toFixed on the wrong thing. It should be:

$("#total-pallets-input").val(totalPallets.toFixed(2));

mjobrien
  • 210
  • 1
  • 6
  • Thank you for pointing out that error. Unfortunately, that didn't solve the problem :( – Tara Jan 10 '14 at 16:59
0

If you're interested in working with money, as said throughout the comments, it's advisable that you work out the whole and the cents as integers, to avoid precision errors with floating points. A simple example of this is to simply separate the whole and the cents and have a method that does the calculations for you:

var Money = (function(){
  function Money(qty) {
    this.whole = 0;
    this.cents = 0;
    this.add(qty);
  }
  Money.prototype.calc = function() {
    while (this.cents > 100) {
      this.cents -= 100;
      this.whole += 1;
    }
    return this;
  };
  Money.prototype.add = function(qty) {
    var parts = qty.split('.');
    this.whole += Number(parts[0]);
    this.cents += Number(parts[1]);
    return this.calc();
  };
  Money.prototype.toString = function() {
    return this.whole +'.'+ this.cents;
  };
  return Money;
}());

var m = new Money('90.75').add('50.43');

console.log(m); //=> {whole: 141, cents: 18}
console.log(m.toString()); //=> "141.18"
elclanrs
  • 92,861
  • 21
  • 134
  • 171
  • Thank you so much for the answer, @elclanrs. I am very very new to Javascript so if you wouldn't mind answering a follow up question, that would be wonderful. How do I implement that into my existing code? Thanks again! – Tara Jan 10 '14 at 17:15
  • jsFiddle doesn't want to load for me today... But all you need to do is create a new instance of `Money` and do the additions with the `add` method and print out the result with `toString`. Instead of using floats, you work with strings. – elclanrs Jan 10 '14 at 17:20
  • Thank you for the help, elclanrs. I'll try to figure out how to do it :) – Tara Jan 10 '14 at 17:24
0

I'd actually want to go through and clean up all that code... but no time for that, so your problem was on line 192 of your fiddle. It should be:

var rowTotal = (numPallets * multiplier).toFixed(2); //it was missing the .toFixed(2)
MikeSmithDev
  • 15,731
  • 4
  • 58
  • 89