Javascript Donation Calculator - Issue with calculation - javascript

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 :)

Use .toFixed(2) which will return a string representing the 2 decimals.
var result = 12.5;
var resultWithDecimals = result.toFixed(2);

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
})
);

Related

My JavaScript financial calculation problem

We are working on financial calculations.
JavaScript front-end code gives different results and C# backend gives different results. Please give me a solution to get the same result in both languages.
I mention two Cases in my example. The first case is not working and another is working.
I want results like C# code those are my expected results.
decimal TotalItemWiseRate = Convert.ToDecimal((Convert.ToDecimal(txtQuantity.Text) * Convert.ToDecimal(txtRate.Text)).ToString("0.00"));
myFunction();
function myFunction() {}
function setDecimalPoint(num) {
var setNumber = parseFloat(num);
if (isNaN(setNumber) || setNumber == 0) {
return setNumber;
} else {
var dotcontain = (setNumber).toString().includes(".");
if (dotcontain == true) {
var a = (setNumber).toString().indexOf(".");
setNumber = (setNumber).toString().substring(0, a + 4);
return (roundNumber(setNumber, 2));
} else {
return (roundNumber(setNumber, 2));
}
}
}
document.getElementById("Case1").innerHTML = "Javascript result: " + 756.05 * 43.5;
document.getElementById("Case11").innerHTML = "Current function: " + setDecimalPoint(756.05 * 43.5);
document.getElementById("Case111").innerHTML = "Calculater result: " + 32888.175;
document.getElementById("Case1111").innerHTML = "C#/My Expected Result: " + 32888.18;
document.getElementById("Case2").innerHTML = "Javascript result: " + 6864.48 / 100;
document.getElementById("Case22").innerHTML = "Current function: " + setDecimalPoint(6864.48 / 100);
document.getElementById("Case222").innerHTML = "Calculater result: " + 68.6448;
document.getElementById("Case2222").innerHTML = "C#/My Expected Result: " + 68.64;
function roundNumber(num, scale) {
if (!("" + num).includes("e")) {
return +(Math.round(num + "e+" + scale) + "e-" + scale);
} else {
var arr = ("" + num).split("e");
var sig = ""
if (+arr[1] + scale > 0) {
sig = "+";
}
return +(Math.round(+arr[0] + "e" + sig + (+arr[1] + scale)) + "e-" + scale);
}
}
<p id="Case1"></p>
<p id="Case11"></p>
<p id="Case111"></p>
<p id="Case1111"></p>
<p id="Case2"></p>
<p id="Case22"></p>
<p id="Case222"></p>
<p id="Case2222"></p>
This single function is the simplest answer I found.
function setDecimalPoint(num) {
if (isNaN(parseFloat(num)))
return 0;
else {
var Number = parseFloat(num);
var multiplicator = Math.pow(10, 2);
Number = parseFloat((Number * multiplicator).toFixed(2));
return (Math.round(Number) / multiplicator);
}
}

JS Changing Classes issue

I'm using API sockets to update the market data.
and I want to classes change when the price goes up and down,
my first class (_class) is working successfully,
second class (_class2) is working at the start by changing to UP (pump) but it won't get back to down (dump) when the price goes down just like the first class. I'm in a bit of confusion coz I'm not so experienced at js.
can anyone tell me where I am mistaken?
window.updateMarkets = function (data) {
if (data.coin != undefined) {
var coin = 'BTC_' + data.coin;
var coin_data = data.msg;
var _coinTable = $('#coins-info-table');
var row = _coinTable.find("tr#" + coin);
price = _coinTable.find("tr#" + coin + " .price");
change = _coinTable.find("tr#" + coin + " .change");
volume = _coinTable.find("tr#" + coin + " .volume");
capital = _coinTable.find("tr#" + coin + " .market_capital");
supply = _coinTable.find("tr#" + coin + " .supply");
_price = formatter.format(coin_data.price);
previous_price = $(price).data('usd');
_class = coin_data.cap24hrChange >= 0 ? 'increment' : 'decrement';
_class2 = coin_data.cap24hrChange >= 0 ? 'pump' :'dump';
if (coin_data.cap24hrChange >= 0.0) {
$(price).html(_price).removeClass().addClass(_class + ' price').data("usd", _price);
} else {
$(price).html(_price).removeClass().addClass(_class + ' price').data("usd", _price);
}
if (coin_data.cap24hrChange >= 0.0) {
$(price).html(_price).removeClass().addClass(_class2 + ' price').data("usd", _price);
} else {
$(price).html(_price).removeClass().addClass(_class2 + ' price').data("usd", _price);
}
$(volume).html(formatter.format(coin_data.volume));
$(capital).html(formatter.format(coin_data.mktcap));
$(supply).html(coin_data.supply);
if (_price !== previous_price) {
_class = previous_price < _price ? 'increment' : 'decrement';
_class2 = previous_price < _price ? 'pump' : 'dump';
$(row).addClass(_class);
setTimeout(function () {
$(row).removeClass('increment decrement');
}, 300);
}
}
};

Update total variable when quantity is changed

I'm having trouble updating the total when I change the "Complete E-Book" product quantity. When I first set the quantity and add it to basket it shows the correct total within the basket but when I change the quantity it adds on to the previous total. Overall I want to be able to add multiple products to the basket total (reason for x += p2Total (x var is what holds the total - Line 86) but while allowing for the Quantity of the product to be changed and then updated in the total.
Codepen Here >
Products in question are the top 2
JS:
// JQuery Functions for NavBar - Class Toggle
(function() {
$('.hamburger-menu').on('click', function() {
$('.bar').toggleClass('animate');
})
})();
(function() {
$('.hamburger-menu').on('click', function() {
$('.bar2').toggleClass('ApprDown');
})
})();
/*
START OF BASKET
START OF BASKET
*/
// Get access to add to basket basket button
var addToBasket = document.querySelector('.atbb');
addToBasket.addEventListener('click', P1);
// Formatter simply formats the output into a currceny format istead of a general number format. This is using the ECMAScript Internationalization API
var formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'GBP',
minimumFractionDigits: 2,
});
var totalBasket
var discountLimit = 10
var discount = 3.50
var x = 0.00
// One big function with different condtions based on the differnt products and then simply concatinate the values where needed
function P1() {
var y = document.getElementById("p1Quant").value;
if (+y > discountLimit) {
var z = 15.000
x = parseFloat(+y) * parseFloat(+z); // + will convert the vars into Numbers etc
document.getElementById("BasketSumData").innerHTML = ("Sub Total: ") + formatter.format(x) + ("<br/>") + ("<hr />") + ("<div class='strike'>Plus £3.50 Delivery</div>") + ("<br/>") + ("<hr />") + ("Total: ") + formatter.format(x)
// Jquery Notificaiton
var truckVar = document.getElementById("truck");
truckVar.setAttribute("class", "animateTruck");
} else if (+y <= 0) {
document.getElementById("BasketSumData").innerHTML = ("Sub Total: ") + formatter.format(0) + ("<br/>") + ("Total: ") + formatter.format(0)
} else {
var z = 15.000
var s = 15.000
x = parseFloat(+y) * parseFloat(+z) + 3.50
var sub = parseFloat(+y) * parseFloat(+s)
document.getElementById("BasketSumData").innerHTML = ("Sub Total: ") + formatter.format(sub) + ("<br/>") + ("<hr />") + ("Plus £3.50 Delivery") + ("<br/>") + ("<hr />") + ("Total: ") + formatter.format(x)
}
}
var addToBasket2 = document.querySelector('.atbb2');
addToBasket2.addEventListener('click', P2);
function P2() {
p2Total = 0.00
var y = document.getElementById("p2Quant").value;
var p2 = 8.00
var p2Total = parseFloat(+y) * parseFloat(+p2); // + will convert the vars into Numbers etc
// var totalBasket = + x + x // javascript add value onto set var
x += p2Total // Append the amount to the basket
document.getElementById("BasketSumData").innerHTML = ("Sub Total: ") + formatter.format(x) + ("<br/>") + ("<hr />") + ("<div class='strike'>Plus £3.50 Delivery</div>") + ("<br/>") + ("<hr />") + ("Total: ") + formatter.format(x)
if (+y <= 0) {
p2Total = 0.00
}
}
Don't add the value to x, add x and p2Total into a new temporary value that is scoped to the function itself and use that.
var tmp_total = x + p2Total;
document.getElementById("BasketSumData").innerHTML = ("Sub Total: ") + formatter.format(tmp_total) + ("<br/>") + ("<hr />") + ("<div class='strike'>Plus £3.50 Delivery</div>") + ("<br/>") + ("<hr />") + ("Total: ") + formatter.format(tmp_total)

Trying to grab a innerhtml from within a innerhtml

So i've recently ran into issues with trying to move specific pieces of a <p> </p> called result. as such i thought hey! wouldn't be easier to break each part inside of result down into another <p>!? well it works lol however trying to grab that inner <p> that in this cause we'll call vault is being difficult. I've tried several methods but cant seem to grab it's value from outside in a document.getElementByID....here's the code below for the html.
document.getElementById("result").innerHTML = Monster + "<p id='vault'> || HP: " + HP + "</p> || Defense: " + Def + " || Attack: " + ATK + " || Can it Dodge/Block: " + DB + " || Can it retaliate: " + RET + " || Initative: " + INT + " || Exp: " + MEXP + " <input type='submit' class='new' onclick='Combat(" + loop + ")' value='FIGHT!'></input>" + "<br><br>" + A;
}
then the script that eventually calls it
function Combat(id){
document.getElementById("vault").innerHTML = id;
document.getElementById("C").value = id
}
So what i'm trying is change id "C" to ID"VAULT" inside of id ("result").
any ideas on why i can't grab vault?
What you want would be easier with Object-oriented JavaScript.
Usually when coding JavaScript you want to be as independent of the DOM (HTML) as possible.
Consider the following example:
/**
* Monster
*/
var Monster = (function() {
function Monster(HP, DEF, ATK, DB, RET, INT, MEXP) {
if (HP === void 0) {
HP = 100;
}
if (DEF === void 0) {
DEF = 10;
}
if (ATK === void 0) {
ATK = 100;
}
if (DB === void 0) {
DB = 10;
}
if (RET === void 0) {
RET = true;
}
if (INT === void 0) {
INT = 100;
}
if (MEXP === void 0) {
MEXP = 100;
}
this.HP = HP;
this.DEF = DEF;
this.ATK = ATK;
this.DB = DB;
this.RET = RET;
this.INT = INT;
this.MEXP = MEXP;
}
/**
* getHTML
*/
Monster.prototype.getHTML = function() {
return "HP: " + this.HP + " || Defense: " + this.DEF + " || Attack: " + this.ATK + " || Can it Dodge/Block: " + this.DB + " || Can it retaliate: " + this.RET + " || Initative: " + this.INT + " || Exp: " + this.MEXP;
};
/**
* attacked
*/
Monster.prototype.attacked = function(damage) {
if (damage === void 0) {
damage = 0;
}
//check defences
if (damage > this.DEF + this.DB) {
//take damage
this.HP -= (damage - this.DEF + this.DB);
}
if (this.HP < 0) {
//Return true if it slew the monster
return true;
} else {
//Return false if the monster survived
return false;
}
};
return Monster;
}());
/**
* Area
*/
var Area = (function() {
function Area(name) {
if (name === void 0) {
name = "Vault";
}
this.name = name;
this.monsters = [];
}
/**
* addMonster
*/
Area.prototype.addMonster = function(monster) {
this.monsters.push(monster);
return this;
};
/**
* attackVault
*/
Area.prototype.assault = function(damage) {
if (damage === void 0) {
damage = 0;
}
//If no monster
if (this.monsters.length < 1) {
alert("You have cleared this vault");
return true;
} else {
//If monsters exists, attack the first
var monsterKilled = this.monsters[0].attacked(damage);
//If the monster was killed
if (monsterKilled) {
//remove monster
this.monsters.splice(0, 1);
//Alert the player
alert("Well done hero!\nOnly " + (this.monsters.length) + " remaining!");
}
}
//Return maybe monsters left?
return this.monsters.length < 1;
};
return Area;
}());
////GRAP HTML ELEMENT
var output = document.getElementById("current-monster");
////RUNNING YOUR GAME
//Build and populate world
var vault = new Area();
vault
.addMonster(new Monster())
.addMonster(new Monster());
//INTERACTION
alert("Start");
//Hit the vault till it is empty
while (vault.assault(45) != true) {
output.innerHTML = vault.monsters[0].getHTML();
alert("Attack!");
}
output.innerHTML = "Victory!";
<h1 id="title">Monster Game!</h1>
<h2 id="current-monster"></h2>
See how i can easily access the data though JavaScript?
When coding a JavaScript game, it makes sense to keep important data and structures in your JavaScript.
Ok so i added the bit - ADyson suggested...
document.getElementById("result").innerHTML = Monster + "<p id='vault(" + loop + ")'> || HP: " + HP + "</p>" + " || Defense: " + Def + " || Attack: " + ATK + " || Can it Dodge/Block: " + DB + " || Can it retaliate: " + RET + " || Initative: " + INT + " || Exp: " + MEXP + " <input type='submit' class='new' onclick='Combat(" + loop + ")' value='FIGHT!'></input>" + "<br><br>" + A;
}
}
}
function Chest(id){
window.open('LootGen.html', '_blank');
}
function Combat(id){
var id = document.getElementById("vault" + id).innerHTML;
document.getElementById("C").value = id;
submit();
}
However now when i run it on the " ).innerHTML;" i'm getting a
MonsterGen.html:426 Uncaught TypeError: Cannot read property
'innerHTML' of nullCombat # MonsterGen.html:426onclick #
MonsterGen.html:1
Ok I found out exactly was was going wrong; it was the naming convention in the <P>.
Originally it was id='vault(" + loop + ")'... this would make it vault(1) etc.... however the getElement was getting it by this call ("vault" + id) so it would call vault1....thus two separate id's entirely....that's why it was returning null.
So I removed the () in the equation and now everything is working beautifully.

Cannot call toFixed on a number variable

I am receiving the follow error in my Console :
" Uncaught TypeError: undefined is not a function "
<script>
//name : calculateResult()-->
function calculateResult() {
console.log("calculateResult() function called!");
//1. Declare Variables-->
var hoursWorked,
jobCategory,
jobCategorySelectedIndex,
hoursEligibleForBasePay,
hoursEligibleForOvertime,
basePayAmount,
overtimePayAmount,
totalPayAmount,
overtimePayRate;
//2. Values for Local Variables-->
hoursWorked = document.getElementById("txthoursWorked").value;
console.log("hoursWorked = " + hoursWorked);
//Get Select element choice: Job Category-->
jobCategorySelectedIndex = document.getElementById("seljobCategory").selectedIndex;
console.log("jobCategorySelectedIndex = " + jobCategorySelectedIndex);
jobCategory = document.getElementById("seljobCategory").options[jobCategorySelectedIndex].value;
console.log("jobCategory = " + jobCategory);
//3. Do Calculations-->
hoursWorked = parseFloat(hoursWorked);
if (jobCategory == "M") {
basePayRate = "25";
} else if (jobCategory == "R") {
basePayRate = "20";
} else if (jobCategory == "S") {
basePayRate = "15";
}
hoursEligibleForBasePay = 40;
basePayAmount = basePayRate * hoursEligibleForBasePay;
console.log("basePayAmount = " + basePayAmount);
console.log("hoursEligibleForOvertime =" + hoursEligibleForBasePay);
if (hoursWorked > 40) {
hoursEligibleForOvertime = hoursWorked - 40;
} else {
hoursEligibleForOvertime = 0;
}
console.log("hoursEligibleForOvertime = " + hoursEligibleForOvertime);
overtimePayRate = 1.5 * basePayRate;
overtimePayAmount = overtimePayRate * hoursEligibleForOvertime;
totalPayAmount = basePayRate + overtimePayAmount;
console.log("overtimePayRate = " + overtimePayRate);
console.log("overtimePayAmount = " + overtimePayAmount);
console.log("totalPayAmount = " + totalPayAmount);
//4. Display Results-->
displayString = "Base Pay " + "$" + basePayAmount.toFixed(2) + "<br />" +
"Overtime Pay " + "$" + overtimePayAmount.toFixed(2) + "<br />"
"Total Pay " + "$" + totalPayAmount.toFixed(2);
document.getElementById("divDisplay").innerHTML = displayString;
}
</script>
the error is in the display string on the Total PayAmount line
any ideas?
The actual error is not actually on that line.
totalPayAmount is defined here:
totalPayAmount = basePayRate + overtimePayAmount;
basePayRate is defined here:
if (jobCategory == "M") {
basePayRate = "25";
} else if (jobCategory == "R") {
basePayRate = "20";
} else if (jobCategory == "S") {
basePayRate = "15";
}
So basePayRate is a string. Then totalPayAmount is also a string, which would not have a toFixed method.

Categories

Resources