Why is this just printing out hello world 9 times instead of adding the event onclick? - javascript

let number1 = document.getElementById("number1");
let number2 = document.getElementById("number2");
let number3 = document.getElementById("number3");
let number4 = document.getElementById("number4");
let number5 = document.getElementById("number5");
let number6 = document.getElementById("number6");
let number7 = document.getElementById("number7");
let number8 = document.getElementById("number8");
let number9 = document.getElementById("number9");
let number0 = document.getElementById("number0");
const numbers_ = [number0, number1, number3, number4, number5, number6,
number7, number8, number9]
function myfunction() {
console.log("hello world");
};
numbers_.forEach(num => {
num.addEventListener("click", myfunction())
});
This is my code. It is just logging Hello World 9 times on load instead of waiting for the click. Please help.

Because you called a function instead of just pass it.
Should be:
numbers_.forEach(num => {
num.addEventListener("click", myfunction)
});

Related

How can I make my calculator evaluate after an operator button is pressed?

Im trying to make a calculator however i cant figure out how to make it chain operations like 4+4+4-5. instead i have to do equals button between each of them(so 4+4 = 8, i then have to press + 4 then = to get a total instead of it doing it after + is pushed. i'd like it to instead calculate when the operator button is pressed, get an answer in that situation.
Here is my javascript. https://codepen.io/hbz19/pen/KKBgYMP
function add(x, y) {
return x + y
};
function subtract(x, y) {
return x - y
};
function multiply(x, y) {
return x * y
};
function divide(x, y) {
return x / y
};
function multiplyarray(array2) {
return array2.reduce((a, b)=> a*b)
};
function operate(firstNum, secondNum, operatorChoice) {
let firstNumToNumber = parseInt(firstNum);
let secondNumToNumber = parseInt(secondNum);
if (operatorChoice === "+") {
let answer = add(firstNumToNumber, secondNumToNumber);
console.log(answer);
displayArea.innerHTML = answer;
} if (operatorChoice === "-") {
answer = subtract(firstNumToNumber, secondNumToNumber);
console.log(answer);
displayValue = answer;
} else if (operatorChoice === "/") {
answer = divide(firstNumToNumber, secondNumToNumber);
console.log(answer);
displayArea.innerHTML = answer;
} else if (operatorChoice === "*") {
answer = multiply(firstNumToNumber, secondNumToNumber);
console.log(answer);
displayArea.innerHTML = answer;
}
};
let answer = ""
let value = "";
let firstNum = "";
let secondNum = "";
let operatorChoice = "";
let currentValue = "";
let previousValue = "";
let displayValue = "";
let displayArea = document.getElementById("display");
displayArea.innerHTML += displayValue;
let buttons = document.querySelectorAll(".numbers");
buttons.forEach(button => {
button.addEventListener("click", (e) => {
updateDisplay(e);
})
});
let updateDisplay = (e) => {
if(displayArea.innerHTML == answer) displayArea.innerHTML = ""
currentValue = e.target.innerHTML;
previousValue = displayArea.innerHTML;
displayValue = previousValue + currentValue;
displayArea.innerHTML = displayValue
}
let operateButtons = document.querySelectorAll(".operator");
operateButtons.forEach(button => {
button.addEventListener("click", (e) => {
startCalculation(e);
})
});
let startCalculation = (e) => {
firstNum = displayArea.innerHTML;
operatorChoice = e.target.innerHTML;
console.log(firstNum);
console.log(operatorChoice);
displayArea.innerHTML = "";
};
let equalButton = document.querySelectorAll(".equal");
equalButton.forEach(button => {
button.addEventListener("click", (e) => {
;
calculate(e);
})
});
let calculate = (e) => {
secondNum = displayValue;
console.log(firstNum, operatorChoice, secondNum);
operate(firstNum, secondNum, operatorChoice);
}
let clearButton = document.querySelectorAll(".reset");
clearButton.forEach(button => {
button.addEventListener("click", (e) => {
clear(e);
})
});
function clear (e) {
let firstNum = "";
let secondNum = "";
let operatorChoice = "";
let currentValue = "";
let previousValue = "";
let displayValue = "";
displayArea.innerHTML = "";
console.log(displayValue, firstNum, secondNum,operatorChoice, currentValue, previousValue)
return displayValue, firstNum, secondNum, operatorChoice, currentValue, previousValue
}````
This is the expected behavior since your functions take 2 numbers. Take operate for example
function operate(firstNum, secondNum, operatorChoice) {
let firstNumToNumber = parseInt(firstNum);
let secondNumToNumber = parseInt(secondNum);
//...
}
The logic you use is : look at operator, based on operator calculate number one with number two
What you need to do is to be able to take more numbers and operators and calculate them, respecting the order of operations, when equal is pressed
There are different ways to go about that, fortunately js has a handy function called eval() that can correctly calculate a string. one easy way is to store your numbers and operators in an array using push everytime a number or an operator is clicked
You'll end up with something like
let numbersToCalculate = [45, '+', 3, '*', 10]
Then we join the array to end up with a string
const numbersStr = numbersToCalculate.join(' ')
we end up with
"45 + 3 * 10"
Then, when equal is pressed we can do
eval(numbersStr)
and get the result
You could also directly push to a string, I personally like to use an array first.

Why i keep getting NaN value in my tip calculator?

I can't find out what is going wrong in my code. Thank you.
I have attached the link to code via codepen.
https://codepen.io/tenzin12/pen/rNmmPbv
`const confirmBtn = document.querySelector(".confirm");
const tipField = document.querySelector(".p1");
const totalField = document.querySelector(".p2");
const tipPercentage = document.querySelector("#tip").children;
const customTip = document.querySelector(".custom").value;
const inputAmt = document.querySelector("#amount").value;
const totalPerson = document.querySelector(".number_of_people").value;
const calcFunction = (bill, percent, diners) => {
const percentage = percent / 100;
const tipPerPerson = (bill * percentage) / diners;
const finalBillPerPerson = bill / diners;
const finalWithTip = finalBillPerPerson + tipPerPerson;
tipField.textContent = tipPerPerson;
totalField.textContent = finalWithTip;
};
for (let i = 0; i < tipPercentage.length; i++) {
tipPercentage[i].addEventListener("click", () => {
if (parseInt(totalPerson) > 0) {
if (tipPercentage[i].value.toUpperCase() === "CUSTOM") {
calcFunction(parseFloat(inputAmt), parseInt(customTip), parseInt(totalPerson));
}
}
calcFunction(parseFloat(inputAmt), parseInt(tipPercentage[i].value), parseInt(totalPerson));
});
}
`
When you need to run calculations on element values, you need to collect those values at the time of calculation. You were collecting them up front - but then when you were calculating the function, it was using those old values. I moved those into your function. Note how I got rid of most of the parseInt and parseFloat functions in favor of the minimal + operator which does the same thing.
Additionally, I simplified the code a little and put in a validation to prevent totals being run on 0 people or 0 amounts. Finally, I changed your for loop into an HTMLCollection forEach loop. I find it is easier to read and maintain
const confirmBtn = document.querySelector(".confirm");
const tipField = document.querySelector(".p1");
const totalField = document.querySelector(".p2");
const tipPercButtons = document.querySelectorAll("#tip input.percentage");
const calcFunction = (bill, percent, diners) => {
const percentage = percent / 100;
const tipPerPerson = (bill * percentage) / diners;
const finalBillPerPerson = bill / diners;
const finalWithTip = finalBillPerPerson + tipPerPerson;
tipField.textContent = tipPerPerson;
totalField.textContent = finalWithTip;
};
tipPercButtons.forEach((el) =>
el.addEventListener("click", (e) => {
const customTip = +document.querySelector(".custom").value;
const inputAmt = +document.querySelector("#amount").value;
const totalPerson = +document.querySelector(".number_of_people").value;
if (isNaN(totalPerson) || isNaN(inputAmt)) {
alert("Please designate the number of people and the amount of the bill")
return;
}
if (totalPerson === 0) return;
let val
if (e.target.value.toUpperCase() === "CUSTOM") val = customTip;
else val = parseInt(e.target.value);
calcFunction(inputAmt, val, totalPerson);
})
);
Updated pen: https://codepen.io/john-tyner/pen/MWmmLMQ?editors=1111
i analysed your code there is some error in fetching the input value in the code.
below is the correct code. Hope this might work
make the following little changes in your code:
const inputAmt = document.querySelector("#amount");
const totalPerson = document.querySelector(".number_of_people");
and this at the bottom outside the if block
calcFunction(
parseFloat(inputAmt.value),
parseInt(tipPercentage[i].value),
parseInt(totalPerson.value)
);
overall your calculator is So interesting.

why does this code change the string but again revert back to original state

function capital(b){
let letter = b[0].toUpperCase();
return letter + b.slice(1);
}
function correction(a){
let place = a.indexOf('_');
let part1 = a.slice(0, place);
let part2 = a.slice(place+1);
a = part1 + capital(part2);
if (a.includes('_'))
correction(a);
return a;
}
When I call correction("Hey_there_How_are_you"), I see in while debugging that it becomes "HeyThereHowAreYou" but again becomes as original string itself. What could be the problem?
You need to return the result of the call in your conditional so that it can be used again.
function capital(b) {
let letter = b[0].toUpperCase();
return letter + b.slice(1);
}
function correction(a) {
let place = a.indexOf('_');
let part1 = a.slice(0, place);
let part2 = a.slice(place + 1);
a = part1 + capital(part2);
if (a.includes('_')) {
return correction(a);
}
return a;
}
let x = correction("Hey_there_How_are_you");
console.log(x);

How to sum the results of a fetch using multiple functions?

I am working with OpenWeatherMapAPI to calculate the sum of precipitation for the previous 5 days. To do this I have 5 async functions with api calls using the fetch api. The data received, that concerns me, is the hourly historic weather data spanning a 24 hour period. Full code bellow. The json response is stored to a constant (Ex.const histData1) where it is then iterated through to sum all of one values over that given 24 hour period. Note: humidity is used as a proof of concept because it hasnt rained here in awhile
for (var i in histData1.hourly){
total1 += histData1.hourly[i].humidity;
};
When I send the resulting value, total1, to the console I receive the expected results.
My trouble is coming when trying to add all of these results together i.e. total1 + total2 + total3 + total4 + total5.
One solution I thought might work was returning the total[1,2,3,4,5] variable at each function and then summing them. Ex.
var rainTotals = getData1() + getData2() + getData3() + getData4() + getData5()
console.log(rainTotals)
This resulted in the following output: [object Promise][object Promise][object Promise][object Promise][object Promise] so it appears to be a datatype issue.
Can anyone shed light as to adding all of the humidity values up from the five separate functions. Feel free to roast my code, I'm pretty new at this.
Thanks!
//WORKS Provies a json of hourly weather data for (1)24 hr period starting 5 days ago.
const fiveDaysAgo = Math.floor((Date.now() / 1000)-432000);
const fivedayURL = "http://api.openweathermap.org/data/2.5/onecall/timemachine?lat=29.8833&lon=-97.9414&dt=" + fiveDaysAgo +"&appid="
async function getData5(){
const response5 = await fetch(fivedayURL)
const histData5 = await response5.json();
var total5 = 0
for (var i in histData5.hourly){
total5 += histData5.hourly[i].humidity;
};
console.log(total5);
return total5;
}
getData5();
const fourDaysAgo = Math.floor((Date.now() / 1000)-345600);
const fourdayURL = "http://api.openweathermap.org/data/2.5/onecall/timemachine?lat=29.8833&lon=-97.9414&dt=" + fourDaysAgo +"&appid=5ffab1cda2c6b2750c78515f41421805"
async function getData4(){
const response4 = await fetch(fourdayURL)
const histData4 = await response4.json();
var total4 = 0;
for (var i in histData4.hourly){
total4 += histData4.hourly[i].humidity
};
console.log(total4);
return total4;
}
getData4();
const threeDaysAgo = Math.floor((Date.now() / 1000)-259200);
const threedayURL = "http://api.openweathermap.org/data/2.5/onecall/timemachine?lat=29.8833&lon=-97.9414&dt=" + threeDaysAgo +"&appid=5ffab1cda2c6b2750c78515f41421805"
async function getData3(){
const response3 = await fetch(threedayURL);
const histData3 = await response3.json();
var total3 = 0;
for (var i in histData3.hourly){
total3 += histData3.hourly[i].humidity;
};
console.log(total3);
return total3;
}
getData3();
const twoDaysAgo = Math.floor((Date.now() / 1000)-172800);
const twodayURL = "http://api.openweathermap.org/data/2.5/onecall/timemachine?lat=29.8833&lon=-97.9414&dt=" + twoDaysAgo +"&appid=5ffab1cda2c6b2750c78515f41421805"
async function getData2(){
const response2 = await fetch(twodayURL);
const histData2 = await response2.json();
var total2 = 0;
for (var i in histData2.hourly){
total2 += histData2.hourly[i].humidity;
};
console.log(total2);
return total2;
}
getData2();
const oneDaysAgo = Math.floor((Date.now() / 1000)-86400);
const onedayURL = "http://api.openweathermap.org/data/2.5/onecall/timemachine?lat=29.8833&lon=-97.9414&dt=" + oneDaysAgo +"&appid=5ffab1cda2c6b2750c78515f41421805"
async function getData1(){
const response1 = await fetch(onedayURL);
const histData1 = await response1.json();
var total1 = 0;
for (var i in histData1.hourly){
total1 += histData1.hourly[i].humidity;
};
console.log(total1);
return total1;
}
getData1();
var rainTotals = getData1() + getData2() + getData3() + getData4() + getData5()
console.log(rainTotals)//returns [object Promise][object Promise][object Promise][object Promise][object Promise]
There are a couple things happening here. Firstly, to answer your question, because your getDataX functions are declared asynchronous, they return Promises that will eventually either resolve or reject with the actual values that you're looking for.
When working with Promises, you need sum the total values after all of these promises have resolved.
Second, you have a bit of duplication in your code. You'll notice that there is very little difference between the innards of your getDataX function. To simplify this, you can extract the differences as function parameters, and encapsulate all the same code within one function.
This would result in an implementation like below:
function getDaysAgo(days) {
return Math.floor((Date.now() / 1000) - (86400 * days))
}
async function getDataForDaysAgo(days) {
let daysAgo = getDaysAgo(days)
const apiURL = `http://api.openweathermap.org/data/2.5/onecall/timemachine?lat=29.8833&lon=-97.9414&dt=${daysAgo}&appid=5ffab1cda2c6b2750c78515f41421805`
const apiResponse = await fetch(apiURL)
const responseJson = await apiResponse.json()
var total = 0
responseJson.hourly.forEach(hour => {
total += hour.humidity
});
console.log(`getDataForDaysAgo(${days}) returns ${total}`)
return total
}
async function getDataSums() {
var data1 = await getDataForDaysAgo(5)
var data2 = await getDataForDaysAgo(4)
var data3 = await getDataForDaysAgo(3)
var data4 = await getDataForDaysAgo(2)
var data5 = await getDataForDaysAgo(1)
return data1 + data2 + data3 + data4 + data5;
}
getDataSums().then(result => {
console.log(result)
})
Async functions always returns a promise.
What you can do is to use Promise.all to aggregate them into one array.
Promise.all([getData1(), getData2(), getData3(), getData4(), getData5()]).then((values) => {
var sum = 0;
for(var i=0; i<values.length; i++){
sum += values[i];
}
console.log(sum);
});
Source : Async Functions
You can use await to get the result of async function.
var rainTotals = await getData1() + await getData2() + await getData3() + await getData4() + await getData5();
Async function delays because it wait for await. 'return' give data immediatly so that's why data give empty object(when console.log(getData1()) only empty objects returned). So getding total data should be awaited. 'total' data in each getData function was pushed into an array. Each getData function get await in asyncAll function to log array at once.
// Data array
let arr = [];
//WORKS Provies a json of hourly weather data for (1)24 hr period starting 5 days ago.
const fiveDaysAgo = Math.floor((Date.now() / 1000)-432000);
const fivedayURL = "http://api.openweathermap.org/data/2.5/onecall/timemachine?lat=29.8833&lon=-97.9414&dt=" + fiveDaysAgo +"&appid=5ffab1cda2c6b2750c78515f41421805"
async function getData5(){
const response5 = await fetch(fivedayURL)
const histData5 = await response5.json();
var total5 = 0
for (var i in histData5.hourly){
total5 += histData5.hourly[i].humidity;
};
console.log(total5);
await arr.push(total5);
return total5;
}
getData5();
const fourDaysAgo = Math.floor((Date.now() / 1000)-345600);
const fourdayURL = "http://api.openweathermap.org/data/2.5/onecall/timemachine?lat=29.8833&lon=-97.9414&dt=" + fourDaysAgo +"&appid=5ffab1cda2c6b2750c78515f41421805"
async function getData4(){
const response4 = await fetch(fourdayURL)
const histData4 = await response4.json();
var total4 = 0;
for (var i in histData4.hourly){
total4 += histData4.hourly[i].humidity
};
console.log(total4);
await arr.push(total4);
return total4;
}
getData4();
const threeDaysAgo = Math.floor((Date.now() / 1000)-259200);
const threedayURL = "http://api.openweathermap.org/data/2.5/onecall/timemachine?lat=29.8833&lon=-97.9414&dt=" + threeDaysAgo +"&appid=5ffab1cda2c6b2750c78515f41421805"
async function getData3(){
const response3 = await fetch(threedayURL);
const histData3 = await response3.json();
var total3 = 0;
for (var i in histData3.hourly){
total3 += histData3.hourly[i].humidity;
};
console.log(total3);
await arr.push(total3);
return total3;
}
getData3();
const twoDaysAgo = Math.floor((Date.now() / 1000)-172800);
const twodayURL = "http://api.openweathermap.org/data/2.5/onecall/timemachine?lat=29.8833&lon=-97.9414&dt=" + twoDaysAgo +"&appid=5ffab1cda2c6b2750c78515f41421805"
async function getData2(){
const response2 = await fetch(twodayURL);
const histData2 = await response2.json();
var total2 = 0;
for (var i in histData2.hourly){
total2 += histData2.hourly[i].humidity;
};
console.log(total2);
await arr.push(total2);
return total2;
}
const oneDaysAgo = Math.floor((Date.now() / 1000)-86400);
const onedayURL = "http://api.openweathermap.org/data/2.5/onecall/timemachine?lat=29.8833&lon=-97.9414&dt=" + oneDaysAgo +"&appid=5ffab1cda2c6b2750c78515f41421805"
async function getData1(){
const response1 = await fetch(onedayURL);
const histData1 = await response1.json();
var total1 = 0;
for (var i in histData1.hourly){
total1 += histData1.hourly[i].humidity;
};
console.log(total1);
//Push data after data asynced
await arr.push(total1);
return total1;
}
//Moved getData function to asyncAll function.
var rainTotals = [];
// Awaited for getData functions, logged total data.
async function asyncAll() {
await getData1();
await getData2();
await getData3();
await getData4();
await getData5();
await console.log(arr.join(', '), 'async');
}
asyncAll();

Multiplication of variables doesn't display

In the code below, the "result" displayed would be zero as 2 * 0. However, there is a button that adds 2 to "number2". Upon clicking on it, the "result" should be 2 * 2, rather than 2 * 0. My problem is that it ends up showing up as zero.
let number1 = 2;
let number2 = 0;
const add2 = () => {
number2 += 2;
display();
};
let result = number1 * number2;
const display = () => {
document.getElementById("result").innerText = result;
};
display();
<p><span id="result"></span></p>
<button onclick="add2();">click me</button>
You need to declare the result variable globally and then make sure you calculate it each time you click the button. Below I've created a function called calculate to do this:
<html>
<body>
<p><span id="result"></span></p>
<button onclick="add2();">click me</button>
<script>
let number1 = 2;
let number2 = 0;
let result;
const add2 = () => {
number2 += 2;
result = calculate();
display();
};
const calculate = () => {
return number1 * number2;
};
const display = () => {
document.getElementById("result").innerText = result;
};
result = calculate();
display();
</script>
</body>
You should declare the result variable globally which always holds the result.
let number1 = 2;
let number2 = 0;
let result;
const add2 = () => {
number2 += 2;
result = number1 * number2;
display();
};
result = number1 * number2;
const display = () => {
document.getElementById("result").innerText = result;
};
display();
<p><span id="result"></span></p>
<button onclick="add2();">click me</button>

Categories