Accessing global variable from function in Javascript - javascript

I would like to access variable from inside a function. The variable tip is innerText of different buttons (5, 6, 7...), but they are in %, so I converted them into numbers. However, the numbers are accessible only from inside the percentage function. When I try to call the function and log the variable, it shows NaN. I would like to use the tip for calculation in calc function always after clicking a respective button. How can I do that?
let tip = 0;
const billInput = document.querySelector(".bill__input");
const peopleInput = document.querySelector(".people__input");
const individualTip = document.querySelector(".conclusion__tip-person");
const individualTotal = document.querySelector(".conclusion__total-person");
const reset = document.querySelector(".conclusion__reset");
const buttons = document.querySelectorAll(".select-tip__button");
function percentage() {
tip = parseInt(this.innerText);
}
buttons.forEach((button) => {
button.addEventListener("click", percentage);
});
function calc() {
if (billInput !== "" && peopleInput === "") {
}
individualTip.textContent = (billInput.value / 100) * tip;
individualTotal.textContent =
"$" + (billInput.value / peopleInput.value).toFixed(2);
}
document.addEventListener("input", calc);
To make it little bit smaller:
I cant access numbers from variable tip, which innerText of buttons with different values (5%, 10%...). These numbers are converted from strings to numbers in the percentage function. I can access the correct tip values after clicking on buttons only if I log it directly inside the percentage function. I would like to use it outside the function, however.
let tip = 0;
function percentage() {
tip = parseInt(this.innerText);
}
buttons.forEach((button) => {
button.addEventListener("click", percentage);
});

you need change string to integer before you calculation
parseInt(peopleInput.value)

In the if (billInput !== "" && peopleInput === ""), you should return to not execute the reset of the function, Also the inputs values be as string format, you need to convert to number, you can use + operator.
let tip = 0;
const billInput = document.querySelector(".bill__input");
const peopleInput = document.querySelector(".people__input");
const individualTip = document.querySelector(".conclusion__tip-person");
const individualTotal = document.querySelector(".conclusion__total-person");
const reset = document.querySelector(".conclusion__reset");
const buttons = document.querySelectorAll(".select-tip__button");
function percentage() {
tip = parseInt(this.innerText);
}
buttons.forEach((button) => {
button.addEventListener("click", percentage);
});
function calc() {
if (billInput !== "" && peopleInput === "") {
// if there no value doesn't execute the rest of the function.
return
}
individualTip.textContent = (+billInput.value / 100) * tip;
individualTotal.textContent =
"$" + (+billInput.value / +peopleInput.value).toFixed(2);
}
document.addEventListener("input", calc);

So for anyone who would encounter similar problem, I solved this one. My variables and fucntions works properly. All I had to do was to put function calc() as the last line inside percentage() function. That did the trick. That's it.

Related

How to retrieve a value from a variable outside of a condition?

I'm learning JS, but I don't know if it's possible to do what I want to achieve.
I have a variable named btcVariationTotal which is in a condition, and I want to retrieve the value of this variable in another variable called tmp, but this variable is not included in the condition.
My problem is that tmp always shows me 0. I don't understand why? And how can I solve this problem, please?
I really want to retrieve the value outside the condition.
console.clear();
let wsBtc = new WebSocket('wss://stream.binance.com:9443/ws/btcusdt#trade');
let btcStockPriceElement1 = document.getElementById('btcValue1');
let btcStockPriceElement2 = document.getElementById('btcValue2');
let btcLastPrice = null;
let btcStockObject = null;
wsBtc.onmessage = (event) => {
btcStockObject = JSON.parse(event.data);
};
let btc1 = 0, btc2 = 0;
let btcVariation_1_2 = 0;
let btcVariationTotal = 0;
let tmp = 0;
let btcRunTimers = setInterval(() => {
let minutes = new Date().getMinutes();
if (minutes === 51) {
let val1 = parseFloat(btcStockObject.p).toFixed(1);
let price = parseFloat(btcStockObject.p).toFixed(1);
btcStockPriceElement1.innerText = price;
btcStockPriceElement1.style.color =
!btcLastPrice || btcLastPrice === price
? 'black'
: price > btcLastPrice
? '#AAFF00'
: 'red';
btcLastPrice = price;
btcStockObject = null;
btc1 = val1;
}
if (minutes === 52) {
let val2 = parseFloat(btcStockObject.p).toFixed(1);
let price = parseFloat(btcStockObject.p).toFixed(1);
btcStockPriceElement2.innerText = price;
btcStockPriceElement2.style.color =
!btcLastPrice || btcLastPrice === price
? 'black'
: price > btcLastPrice
? '#AAFF00'
: 'red';
btcLastPrice = price;
btcStockObject = null;
btc2 = val2;
btcVariation_1_2 = ( (parseFloat(btc2) - parseFloat(btc1)) / btc1 * 100);
document.getElementById("btcResult1").innerHTML = btcVariation_1_2.toFixed(2);
}
btcVariationTotal = (parseFloat(btcVariation_1_2));
console.log("btc variation => " + btcVariationTotal);
document.getElementById("result").innerHTML = btcVariationTotal.toFixed(2);
tmp = btcVariationTotal;
}, 60000);
console.log("tmp => " + tmp);
The good news is that you are in fact doing what you want: you are retrieving
the value of the btcVariationTotal variable, and storing in tmp, which is
defined in the outer scope, outside of your setInterval callback.
The only problem you have is that you can't display a modified tmp, and
that's because you only call console.log before setting tmp, you never
call it after it has been changed. User Ivar has tried to explain that in
the comments, maybe I can detail it a bit more:
At time t=0, you set tmp = 0, you set your timers with setInterval, associating
a callback function (which does NOT run at this point), and then you call
console.log to display tmp (it's 0, because no callback has ever run).
At time t=60s, your callback runs, sets btcVariationTotal to some value, and
assigns that to tmp. No attempt is made to display the tmp value. Then this
gets repeated every 60s.
So what's missing is for you to write some code that displays the tmp value
after it has been changed. One way to do that, is to put that code inside
some other callback and arrange for it to be called. I suggest a simple
button. Add the following somewhere in your html page:
<button id="show-tmp">Show tmp</button>
Add the following lines at the end of your JS code:
let btn = document.getElementById('show-tmp');
btn.onclick = function() {
console.log(`tmp: ${tmp}`);
}
Now clicking on the button will show you the value inside tmp; if you do it
before the first 60 seconds, it will show 0; if you do it afterwards, it will
show whatever value was in btcVariationTotal.

calculating an equation given a certain input from a user with JavaScript

JavaScript newbie here.
I am tasked with calculating a user's monthly payment by using a given equation. I am having trouble with getting the values from the user.
const loanAmount = document.getElementById('loan-amount');
const loanYears = document.getElementById('loan-years');
const loanRate = document.getElementById('loan-Rate');
const span = document.querySelector('span');
const form = document.getElementById("calc-form");
form.addEventListener("submit", function (e) {
e.preventDefault();
console.log('hello')
makeLogo();
});
function makeLogo(loanAmount, loanYears, loanRate) {
const principle = loanAmount.value
const n = loanYears.value * 12;
const i = loanRate.value / 12;
const monthylPayment = (principle* i)/1-(1+ i)** -(n);
span.innerText = monthylPayment;
}
This is what I have so far and am getting an error for the variables in the makeLogo function.
It's a good idea to separate your inputs, calculations and rendering into separate functions. try to keep functions as simple as possible.
You will need to re-evaluate your monthly cost calculator, but here is a working example which takes input, calculates and then renders into form fields.
document.getElementById("calc-form").addEventListener('submit', (e) => {
e.preventDefault();
var loanAmount = document.getElementById('loan-amount').value;
console.log(loanAmount);
var loanYears = document.getElementById('loan-years').value;
var loanRate = document.getElementById('loan-rate').value;
var monthlyPayment = makeLogo( loanAmount, loanYears, loanRate );
console.log(monthlyPayment);
// the monthly has now been calculated, simply put it where you'd like
var calculated = document.getElementById('calculated');
calculated.value = monthlyPayment;
var totalRepayment = document.getElementById('totalRepayment');
totalRepayment.value = monthlyPayment * ( loanYears * 12 );
} );
function makeLogo( principle, loanYears, loanRate) {
var n = loanYears * 12;
var i = loanRate / 12;
var result = ( principle * i) / 1 - ( 1 + i )**-( n );
return result;
}
<html>
<form action='submit' id ='calc-form'>
Loan Amount:<input id ='loan-amount'></input><BR/>
Loan Years:<input id='loan-years'></input><BR/>
Loan Rate:<input id='loan-rate'></input><BR/>
<input type='submit'>
</form>
<span id='span-output'>
Monthly Payment :<input id='calculated' readonly><BR/>
Total Re-Payment :<input id='totalRepayment' readonly>
</span>
</html>
The error you are seeing is likely because the makeLogo function is trying to access the value property of the loanAmount, loanYears, and loanRate variables. Still, they are DOM elements and not their values.
You can fix this by accessing the value property of the DOM elements before passing them to the function like so:
form.addEventListener("submit", function (e) {
e.preventDefault();
console.log('hello')
const principle = loanAmount.value;
const n = loanYears.value * 12;
const i = loanRate.value / 12;
makeLogo(principle, n, i);
});
function makeLogo(principle, n, i) {
const monthylPayment = (principle* i)/1-(1+ i)** -(n);
span.innerText = monthylPayment;
}
This way, the makeLogo function receives the values of the input fields as arguments and can perform the calculation correctly.
Also, make sure that you are getting the right input from the user by checking the value of each element by doing the following:
console.log(loanAmount.value,loanYears.value,loanRate.value)
and check if they are the values that you are expecting.

Sum in constructor

I'm trying to solve the problem. When the user enter two numbers via ** prompt **, after the display shows the final result. Simple constructor, but this code only accepts the first value, I cannot force it to take the second one too, in order for sum both values
function Num (firstNum) {
this.firstNum = firstNum;
this.read = function() {
this.value = this.x + this.firstNum; {
return this.x = +prompt('a');
}
};
}
let num = new Num(10);
num.read();
num.read();
alert(num.value);
As other commenters have suggested you should probably edit your question to make it clearer. But if I had to take a guess here's my answer:
Lookup "curry functions" or "partial application". You can basically use closures to stash the value from the first prompt until you receive the value from the second.
const sumTwo = firstNum => secondNum => firstNum + secondNum;
// then when you want to use it;
const plusTen = sumTwo(prompt(10);
const resultA = plusTen(prompt(2)); // this will be 12
const resultB = plusTen(prompt(5)); // this will be 15
solve
function Num (firstNum) {
this.value = firstNum;
this.read = function() {
this.value += +prompt('a?', 0);
};
}
let num = new Num(10);
num.read();
num.read();
alert(num.value);

Why does if statement not work and make my element disappear using display: none?

I am building a tip calculator and I couldn't make the if statement in my function work it just skips to calculating.
function calculate() {
var bill = parseInt(document.getElementById("bill").value);
var tip = parseInt(document.getElementById("tip").value) * .01;
var persons = parseInt(document.getElementById("persons").value);
if (bill == "" || tip == "") {
alert("Please enter value");
return;
};
if (persons == "" || persons <= 1) {
persons = 1;
document.getElementById("perPerson").style.display = "none";
} else {
}
let totalTipPer = (bill * tip) / persons;
let totalPer = (bill + (tip * 100)) / persons;
let totalTip = bill * tip;
let total = bill + (tip * 100);
totalTipPer = totalTipPer.toFixed(2);
totalPer = totalPer.toFixed(2);
total = total.toFixed(2);
totalTip = totalTip.toFixed(2);
document.getElementById("total-tip/person").innerHTML = totalTipPer;
document.getElementById("total-price/person").innerHTML = totalPer;
document.getElementById("total-tip").innerHTML = totalTip;
document.getElementById("total-price").innerHTML = total;
}
document.getElementById("calculate").onclick = function () {
calculate();
document.getElementById('results').style.display = 'block';
}
I expect the div encapsulating Tip Amount per person and total per person and to not appear when the input value of persons is empty.
Function parseInt returns 'An integer number parsed from the given string. If the first character cannot be converted to a number, NaN is returned.'
if you rpovide an empty value ('') it will return
NaN which is not equal to anything, even itself.
there are several ways to fix this:
check if it is a NaN with Number.isNaN(var)
use an intermediate value like var personsValue and check if it is equal to empty string ''.
use Hybrid suggested solution and assign a 0
value for falsy value('', undefined, n
ull etc...)
The issue is that persons becomes NaN, since if the value is left blank, "" becomes NaN when it is run through parseInt().
The way to fix this is by defaulting it to 0 if the field is left blank.
var persons = parseInt(document.getElementById("persons").value || 0);
as others pointed out parseInt is returning NaN if the field is blank, but this will also happen if the user inputs $5.00 for example.
Here's one way to make sure the value can be converted to a number before doing so.
// This function determines if a JavaScript String can be converted into a number
function is_numeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
function calculate() {
// first put the input values into separate variables
billValue = document.getElementById("bill").value;
tipValue = document.getElementById("tip").value;
personsValue = document.getElementById("persons").value;
// use the is_numeric() function above to check if the values can be converted to numeric
if (!is_numeric(billValue) || !is_numeric(tipValue)) {
alert("Please enter values for bill and tip");
return;
}
// the rest of your code here
}
Hope this helps.

Random Number with javascript or jquery

I am trying to make a script to pick random number between two numbers . but it picks same number sometimes. i donot want to repeat same number until array is finished .
Here is my code
$(document).ready(function () {
abc();
test = array();
function abc() {
res = randomXToY(1, 10, 0);
$('#img' + res).fadeTo(1200, 1);
//$(this).addClass('activeImg');
//});
setTimeout(function () {
removeClassImg(res)
}, 3000);
}
function removeClassImg(res) {
$('#img' + res).fadeTo(1200, 0.1);
//$('#img' + res).removeClass('activeImg');
abc();
}
function randomXToY(minVal, maxVal, floatVal) {
var randVal = minVal + (Math.random() * (maxVal - minVal));
return typeof floatVal == 'undefined' ? Math.round(randVal) : randVal.toFixed(floatVal);
}
});
Does Anybody have idea about this ...
You'll have to maintain a list of numbers that have already been generated, and check against this list. Re-generate a new number if you find a dupe.
If you do not want the random numbers repeating themselves you have to keep track of the some way.
If you have the range you are dealing with is relatively small, you can create an array with all possible results and simply randomly pick out of it.
function Randomizer(minVal, maxVal, floatVal){
var possible_results = []; // for larger arrays you can build this using a loop of course
var randomization_array = [];
var count = minVal;
var incrementor = floatVal || 1; // set the distance between possible values (if floatVal equals 0 we round to 1)
while (count <= maxVal) {
possible_results.push(count);
count += incrementor;
}
this.run = function(){
// if randomization_array is empty set posssible results into it
randomization_array = randomization_array.length ? randomization_array : $.merge(randomization_array, possible_results);
// pick a random element within the array
var rand = Math.floor(Math.random()*randomization_array.length);
// return the relevant element
return randomization_array.splice(rand,1)[0];
}
}
and in order to use it (it creates a specialized object for each possible range):
rand = new Randomizer(1,10,0);
rand.run();
note that this approach does not work well for very large ranges

Categories

Resources