0

I am having a bit of an issue with my JavaScript Donation Calculator, It works well, however when I am calculating the percentage of 50, it comes up as $12.5 and I would like it to be $12.50, this also effects $7.50 it shows up at 7.5.

I have included the code below

// set the variables
var donationSubmit = document.getElementById('donationSubmit');
// turn the outputs into variables as I am sure they will be used more than once per page load
var afterCreditOutput = document.getElementById('afterCreditOutput')
var totalCostOutput = document.getElementById('totalCostOutput');
/* jquery stuffs */
$maxDonation = 1200
// calculate the value on keyup
$inputValue = $('input[name="donation_amount"]');
$('#customDonationAmount').keyup(function(){
if ($inputValue.val() > $maxDonation) {
$inputValue.val($maxDonation);
}
if ($inputValue.val() === "") {
afterCreditOutput.innerHTML = ("Please enter a value or choose from one of the preset values above");
totalCostOutput.innerHTML = ("");
}
calculateCustomTaxCredit();
});
// calculate the value on enter
/*
$inputValue.bind('keypress', function(e) {
if(e.which == 13) {
calculateCustomTaxCredit();
}
});
*/
/* end of jquery */
// validate the keystrokes and ensure the only things pressed are numbers
function validate(evt) {
var theEvent = evt || window.event;
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode(key);
var regex = /[0-9]|\./;
if (!regex.test(key)) {
theEvent.returnValue = false;
if (theEvent.preventDefault) theEvent.preventDefault();
}
}
// super ugly and hacky but it does the job.
document.getElementById('donationAmount-20').onclick = applyButtonAmount;
document.getElementById('donationAmount-50').onclick = applyButtonAmount1;
document.getElementById('donationAmount-100').onclick = applyButtonAmount2;
document.getElementById('donationAmount-400').onclick = applyButtonAmount3;
document.getElementById('donationAmount-1200').onclick = applyButtonAmount4;
function applyButtonAmount() {
document.forms["donation-form"]["donation_amount"].value = (20);
calculateCustomTaxCredit()
}
function applyButtonAmount1() {
document.forms["donation-form"]["donation_amount"].value = (50);
calculateCustomTaxCredit()
}
function applyButtonAmount2() {
document.forms["donation-form"]["donation_amount"].value = (100);
calculateCustomTaxCredit()
}
function applyButtonAmount3() {
document.forms["donation-form"]["donation_amount"].value = (400);
calculateCustomTaxCredit()
}
function applyButtonAmount4() {
document.forms["donation-form"]["donation_amount"].value = (1200);
calculateCustomTaxCredit()
}
/* Where all the magic happens */
// Helper Funcs
// oh JavaScript why are you so bad at rounding.
function round(number, precision) {
var shift = function (number, precision, reverseShift) {
if (reverseShift) {
precision = -precision;
}  
numArray = number.toString().split("e");
return +(numArray[0] + "e" + (numArray[1] ? (+numArray[1] + precision) : precision));
};
// number = shift(number, precision, false);
// number = Math.round(number);
// number = shift(number, precision, true);
return shift(Math.round(shift(number, precision, false)), precision, true);
}
// return a percentage
function per(num, amount){
return num*amount/100;
}
// calculate
function calculateCustomTaxCredit() {
var donationAmount = document.forms["donation-form"]    ["donation_amount"].value;
// if there is nothing in the input then fail
if (donationAmount === "") {
afterCreditOutput.innerHTML = ("Please enter a value or choose a preset value");
// check has passed - this is a number
}else { 
if(donationAmount <= 100 ) {
console.log("Initial amount: " + donationAmount);
var costAfterCredit = per(donationAmount, 25);
var credit = per(donationAmount, 75);
var cleanCostAfterCredit = round(costAfterCredit, 2)
var cleanCredit = round(credit, 2);
console.log(donationAmount);
if(donationAmount == '50') {
alert('hi');
}
afterCreditOutput.innerHTML = ("Cost after Tax Credit:" + " <span                     
class='green'>$" + cleanCostAfterCredit + "</span>");
totalCostOutput.innerHTML = ("Total Amount:" + " <span class='green'>$" +         
donationAmount + "</span>");
//TESTING CODE
console.log('75% tax credit');
console.log('Money saved: ' + credit);
console.log('Money spent: ' + costAfterCredit);
console.log('Money saved: ' + cleanCredit + " CLEAN");
console.log('Money spent: ' + cleanCostAfterCredit + " CLEAN");
}else if(donationAmount > 100 && donationAmount <= 550) {
console.log("Initial amount: " + donationAmount);
var costAfterCredit = per(donationAmount, 50);
var credit = per(donationAmount, 50);
var cleanCostAfterCredit = round(costAfterCredit, 2)
var cleanCredit = round(credit, 2);
afterCreditOutput.innerHTML = ("Cost after Tax Credit: Approx" + " <span class='green'>$" + cleanCostAfterCredit + "</span>");
totalCostOutput.innerHTML = ("Total Amount:" + " <span class='green'>$" + donationAmount + "</span>");
//TESTING CODE
//console.log('75% tax credit');
//console.log('Money saved: ' + credit);
//console.log('Money spent: ' + costAfterCredit);
//console.log('Money saved: ' + cleanCredit + " CLEAN");
//console.log('Money spent: ' + cleanCostAfterCredit + " CLEAN");
}else {
console.log("Initial amount: " + donationAmount);
var costAfterCredit = per(donationAmount, 66.6666666666666);
var credit = per(donationAmount, 33.3333333333333);
var cleanCostAfterCredit = round(costAfterCredit, 2)
var cleanCredit = round(credit, 2);
if(cleanCredit >= 500) {
cleanCostAfterCredit = donationAmount - 500;
}
afterCreditOutput.innerHTML = ("Cost after Tax Credit:" + " <span c        class='green'>$" + cleanCostAfterCredit + "</span>");
totalCostOutput.innerHTML = ("Total Amount:" + " <span class='green'>$" +     donationAmount + "</span>");
//TESTING CODE
//console.log('75% tax credit');
//console.log('Money saved: ' + credit);
//console.log('Money spent: ' + costAfterCredit);
//console.log('Money saved: ' + cleanCredit + " CLEAN");
//console.log('Money spent: ' + cleanCostAfterCredit + " CLEAN");
}
}
};

Here is also a pastebin with more readable code: goo.gl/UQZrik

In the end I am trying to have the variable cleanCostAfterCredit set to 12.50 instead of 12.5 when a calculation is done. Also if anyone can give me any tips on making my code more efficient I would really appreciate it. please lay on the constructive criticism :)

  • 1
    Just an FYI - `12.5` means 12 dollars and 50 cents and not 5 cents, otherwise it would have been `12.05` :) – Rahul Desai Apr 04 '18 at 23:57
  • Yes I am aware of that, I just want it to be shown, for example if I put 50 into my calculator, it will spit out 25% which is shown as 12.5, how would I have it shown as 12.50? – chris lawson Apr 04 '18 at 23:58
  • 1
    Basically, you need to pad your number. If you call `.toFixed(2)` on the number, it will return it as a string with a fixed number of decimal places. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed – Brandon Anzaldi Apr 05 '18 at 00:01
  • Possible duplicate of [Format number to always show 2 decimal places](https://stackoverflow.com/questions/6134039/format-number-to-always-show-2-decimal-places) – Raul Sauco Apr 05 '18 at 00:04
  • @RaulSauco I don't think it is because this is formatting money and may need to be culture aware. See my answer – Ruan Mendes Apr 05 '18 at 00:21
  • @JuanMendes your answer is the best, a much better way to do it. I still think that the flag is valid until the OP edits the question, notice that in the code posted the OP does not take into account the locale when formatting the output string, the original question always prepends a `$` to the numeric value formatted to display 2 decimals. So the OP is not really asking how to format the result into a currency, but asking how to format a numeric value to always display two decimal places, if you look at other answers you will see that most people interpret it that way. In that case is a dup. – Raul Sauco Apr 05 '18 at 00:32
  • @JuanMendes in my opinion the best thing to do would be to modify the question so it asks something like _"How to properly format currency values entered by the user"_ and mark your answer as accepted. That would have more value for future users. It may also be a duplicate though. – Raul Sauco Apr 05 '18 at 00:34

2 Answers2

0

Use .toFixed(2) which will return a string representing the 2 decimals.

var result = 12.5;
var resultWithDecimals = result.toFixed(2);
Fecosos
  • 944
  • 7
  • 17
0

The toFixed method formats floats but is not culture aware.

donationAmount.toFixed(2)

If you want to be culture aware, you should use toLocaleString

console.log(
    // This uses the default locale
    (12.5).toLocaleString(undefined, {
        style: 'currency',
        currency: 'USD',
        minimumFractionDigits: 2
    })
);

console.log(
    (1).toLocaleString('pt-br', {
        style: 'currency',
        currency: 'USD',
        minimumFractionDigits: 2
    })
);
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217