I want to change the index of newAr on each click and console log the values of next object in newAr showed in looper function
Note: I only want the index second object values on second click and third object values in newAr on third click
HTML only has a button nothing else
const button = document.querySelector("button");
let firstVar = () => {
const firstVarVariable = Math.round(Math.random() * 10);
if (firstVarVariable < 5) {
return true;
} else {
return false;
}
};
let secondVar = () => {
const firstVarVariable = Math.round(Math.random() * 10);
if (firstVarVariable < 5) {
return true;
} else {
return false;
}
};
let thirdVar = () => {
const firstVarVariable = Math.round(Math.random() * 10);
if (firstVarVariable < 5) {
return true;
} else {
return false;
}
};
const newAr = [];
const pusher = () => {
newAr.push({
one: firstVar(),
two: secondVar(),
three: thirdVar(),
});
console.log(newAr);
looper();
};
const looper = () => {
for (const value of newAr) {
console.log(value.one);
console.log(value.two);
console.log(value.three);
}
// I want to change the index of newAr array on click
// Like i want to console log first object in array on first click
// and second object on other click and third object
// alsp please tell me if i can change some approch
};
button.addEventListener("click", () => {
pusher();
});
let randomBool = () => Math.random() < 0.5;
// all three functions did the same thing...
const newAr = [];
const pusher = () => {
newAr.push({
one: randomBool(),
two: randomBool(),
three: randomBool(),
});
console.log(newAr);
looper();
};
let index = 0; // counter / array index
const looper = () => {
let value = newAr[index++]; // always getting the next element (starting from 0).
console.log(value.one);
console.log(value.two);
console.log(value.three);
};
/***/
const button = document.querySelector("button");
button.addEventListener("click", () => {
pusher();
});
<button>Test</button>
Related
I have a function called debouncedGetScrolledDownPercentage that I want to return the scrollPercentage. As it is debounced, it incorrectly returns undefined, presumably because the debounce function does not return anything.
How can debouncedGetScrolledDownPercentage() return the scrollPercentage, so that scrolledDownPercentage: debouncedGetScrolledDownPercentage() is not undefined? I assume a global variable accessible to all scopes could solve it, but I would prefer a different solution.
Any help would be appreciated, thank you.
For context, here is all the code:
window.onbeforeunload = function() { return "Are you sure you want to leave?"; }; // for testing, so you can click close and the browser won't close and you can still see the logs
// initial data
let bounced = true;
const sessionStartTime = new Date();
let maxScrollPosition = 0;
let totalScrollDistance = 0;
// functions
const setBouncedToFalse = () => {
bounced = false;
document.removeEventListener("click", setBouncedToFalse);
};
const calculateSessionTime = () => {
const sessionEndTime = new Date();
return sessionEndTime - sessionStartTime; // sessionTimeMs
}
const debounce = (func, delay) => {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
};
const debouncedGetScrolledDownPercentage = debounce(() => {
// const debouncedGetScrolledDownPercentage = debounce((callback) => {
const scrollPosition = window.scrollY;
let scrollPercentage = 0;
if (scrollPosition > maxScrollPosition) {
const scrollDistance = scrollPosition - maxScrollPosition;
totalScrollDistance += scrollDistance;
maxScrollPosition = scrollPosition;
const maxPossibleScrollDistance = document.documentElement.scrollHeight - window.innerHeight;
scrollPercentage = Math.round(totalScrollDistance / maxPossibleScrollDistance * 100);
}
return scrollPercentage;
// callback(scrollPercentage);
}, 200);
const processData = () => {
const userData = {
sessionTimeMs: calculateSessionTime(),
bounced,
scrolledDownPercentage: debouncedGetScrolledDownPercentage() // incorrectly returns undefined
};
debouncedGetScrolledDownPercentage((scrollPercentage) => {
userData.scrolledDownPercentage = scrollPercentage;
console.log('userData: ', userData);
});
}
// events
document.addEventListener("click", setBouncedToFalse); // track clicks (if user bounces)
window.addEventListener('scroll', debouncedGetScrolledDownPercentage); // needed?
window.addEventListener("beforeunload", processData); // process data before user leaves
Here is the link to my repo's github page, so you can properly see what I mean.
I am currently having an issue with my triviaGame function when trying to make it recursive, but it's sort of "backfiring" on me in a sense.
You'll notice after you answer the first question, everything seems fine. It goes to the next question fine. After that though, it seems like the iterations of it double? The next answer it skips 2. After that, 4. And finally the remaining 2 (adding up to 10, due to how I am iterating over them).
How might I be able to correctly iterate over a recursive function, so it correctly calls all 10 times, and then returns when it is done?
Been struggling with this for hours, and just can't seem to get it to work. My javascript code is below, sorry for any headaches that it may give you. I know I make some questionable programming decisions. Ignore some of the commented out stuff, it's not finished code yet. I'm a beginner, and hope that once I learn what's going on here it will stick with me, and I don't make a stupid mistake like this again.
const _URL = "https://opentdb.com/api.php?amount=1&category=27&type=multiple";
const _questionHTML = document.getElementById("question");
const _answerOne = document.getElementById("answer-1");
const _answerTwo = document.getElementById("answer-2");
const _answerThree = document.getElementById("answer-3");
const _answerFour = document.getElementById("answer-4");
const btns = document.querySelectorAll("button[id^=answer-]");
var runCount = 1;
var correct = 0;
// Credits to my friend Jonah for teaching me how to cache data that I get from an API call.
var triviaData = null;
async function getTrivia() {
return fetch("https://opentdb.com/api.php?amount=1&category=27&type=multiple")
.then((res) => res.json())
.then((res) => {
triviaData = res;
return res;
});
}
// anywhere I want the trivia data:
// const trivia = await getTrivia() --- makes the call, or uses the cached data
const shuffleArray = (array) => {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
async function triviaGame() {
const trivia = await getTrivia();
async function appendData() {
let totalAnswers = [
...trivia.results[0].incorrect_answers,
trivia.results[0].correct_answer,
];
// Apparently I need 2 different arrays to sort them because array variables are stored by reference? Learn something new everyday I guess.
let totalAnswers2 = [...totalAnswers];
let sorted = shuffleArray(totalAnswers2);
// Ensures the proper symbol shows instead of the HTML entities
const doc = new DOMParser().parseFromString(
trivia.results[0].question,
"text/html"
);
_questionHTML.textContent = doc.documentElement.textContent;
console.log(trivia.results[0].correct_answer, "- Correct Answer");
// Appends info to the DOM
_answerOne.textContent = sorted[0];
_answerTwo.textContent = sorted[1];
_answerThree.textContent = sorted[2];
_answerFour.textContent = sorted[3];
}
async function checkAnswer() {
btns.forEach((btn) => {
btn.addEventListener("click", (event) => {
console.log(runCount);
if (event.target.textContent === trivia.results[0].correct_answer) {
event.target.style.backgroundColor = "#52D452";
// Disables all buttons after one has been clicked.
btns.forEach((btn) => {
btn.disabled = true;
});
setTimeout(() => {
if (runCount === 10) {
return;
}
runCount++;
correct++;
btns.forEach((btn) => {
btn.disabled = false;
});
btn.style.backgroundColor = "";
document.getElementById(
"amount-correct"
).textContent = `${correct}/10`;
triviaGame();
}, 2000);
} else {
event.target.style.backgroundColor = "#FF3D33";
btns.forEach((btn) => {
btn.disabled = true;
});
// document.getElementById("correct-text").textContent =
// trivia.results[0].correct_answer;
// document.getElementById("correct-answer").style.visibility =
// "visible";
setTimeout(() => {
if (runCount === 10) {
return;
}
// document.getElementById("correct-answer").style.visibility =
// "hidden";
btns.forEach((btn) => {
btn.disabled = false;
btn.style.backgroundColor = "";
});
runCount++;
triviaGame();
}, 3500);
}
});
});
}
checkAnswer();
appendData();
}
triviaGame();
Any/All responses are much appreciated and repsected. I could use any help y'all are willing to give me. The past 6 hours have been a living hell for me lol.
It's skipping questions once an answer is clicked because every time a button is clicked, another event listener is added to the button, while the original one is active:
On initial load: triviaGame() runs which makes checkAnswer() run which adds event listeners to each of the buttons.
Event listeners on buttons: 1.
Answer button is clicked, triviaGame() runs which makes checkAnswer() run which adds event listeners to each of the buttons.
Event listeners on buttons: 2.
Answer button is clicked, triviaGame() runs twice (from the 2 listeners attached) which makes checkAnswer() run twice where both invocations adds event listeners to each of the buttons.
Event listeners on buttons: 4.
etc.
To fix this, I moved the content of checkAnswer() outside of any functions so it only ever runs once. However, doing this, it loses reference to the upper scope variable trivia. To resolve this, I used the triviaData variable instead which checkAnswer() would have access to and I change references in appendData() to match this. Now, triviaGame() function only exists to call appendData() function inside it; there is little point in this so I merge the two functions together into one function, instead of two nested inside each other.
const _URL = "https://opentdb.com/api.php?amount=1&category=27&type=multiple";
const _questionHTML = document.getElementById("question");
const _answerOne = document.getElementById("answer-1");
const _answerTwo = document.getElementById("answer-2");
const _answerThree = document.getElementById("answer-3");
const _answerFour = document.getElementById("answer-4");
const btns = document.querySelectorAll("button[id^=answer-]");
var runCount = 1;
var correct = 0;
// Credits to my friend Jonah for teaching me how to cache data that I get from an API call.
var triviaData = null;
async function getTrivia() {
return fetch("https://opentdb.com/api.php?amount=1&category=27&type=multiple")
.then((res) => res.json())
.then((res) => {
triviaData = res;
return res;
});
}
// anywhere I want the trivia data:
// const trivia = await getTrivia() --- makes the call, or uses the cached data
const shuffleArray = (array) => {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
async function appendData() {
triviaData = await getTrivia();
let totalAnswers = [
...triviaData.results[0].incorrect_answers,
triviaData.results[0].correct_answer,
];
// Apparently I need 2 different arrays to sort them because array variables are stored by reference? Learn something new everyday I guess.
let totalAnswers2 = [...totalAnswers];
let sorted = shuffleArray(totalAnswers2);
// Ensures the proper symbol shows instead of the HTML entities
const doc = new DOMParser().parseFromString(
triviaData.results[0].question,
"text/html"
);
_questionHTML.textContent = doc.documentElement.textContent;
console.log(triviaData.results[0].correct_answer, "- Correct Answer");
// Appends info to the DOM
_answerOne.textContent = sorted[0];
_answerTwo.textContent = sorted[1];
_answerThree.textContent = sorted[2];
_answerFour.textContent = sorted[3];
}
btns.forEach((btn) => {
btn.addEventListener("click", (event) => {
console.log(runCount);
if (event.target.textContent === triviaData.results[0].correct_answer) {
event.target.style.backgroundColor = "#52D452";
// Disables all buttons after one has been clicked.
btns.forEach((btn) => {
btn.disabled = true;
});
setTimeout(() => {
if (runCount === 10) {
return;
}
runCount++;
correct++;
btns.forEach((btn) => {
btn.disabled = false;
});
btn.style.backgroundColor = "";
document.getElementById(
"amount-correct"
).textContent = `${correct}/10`;
appendData();
}, 2000);
} else {
event.target.style.backgroundColor = "#FF3D33";
btns.forEach((btn) => {
btn.disabled = true;
});
// document.getElementById("correct-text").textContent =
// trivia.results[0].correct_answer;
// document.getElementById("correct-answer").style.visibility =
// "visible";
setTimeout(() => {
if (runCount === 10) {
return;
}
// document.getElementById("correct-answer").style.visibility =
// "hidden";
btns.forEach((btn) => {
btn.disabled = false;
btn.style.backgroundColor = "";
});
runCount++;
appendData();
}, 3500);
}
});
});
appendData();
<div id="amount-correct"></div>
<h1 id="question"></h1>
<button id="answer-1"></button>
<button id="answer-2"></button>
<button id="answer-3"></button>
<button id="answer-4"></button>
I have two buttons (each of them has a value which matches the id of a dish in the food menu) with two EventListeners. One button for adding something to a shopping cart and one button to remove something from the shopping cart. My problem is, that i cant figure out how to pass the Eventlistener to the correct class function. This is my code so far:
class Cart {
constructor() {
this.inhalt = [];
}
add(item) {
this.inhalt.push(item);
console.log(this.inhalt)
}
remove(item) {
for (let i = 0; i < this.inhalt.length; i++) {
if (this.inhalt[i].id === item.id) {
this.inhalt.splice(i, 1);
console.log(this.inhalt)
}
}
}
sum() {
let s = null;
this.inhalt.price.forEach(element => {
s += element
});
console.log(s)
}
}
const myCart = new Cart();
function getItem(type) {
let item = null;
for (let i=0; i<speisekarte.length; i++) {
if (speisekarte[i].id === this.value) {
item = speisekarte[i];
break;
}
}
if (type == "plus") {myCart.add(item)}
else if (type == "minus") {myCart.remove(item)};
}
let plus = document.querySelectorAll(".kaufen");
plus.forEach(el =>{
let type = "plus"; el.addEventListener("click", getItem(type));
});
let minus = document.querySelectorAll(".zurück");
minus.forEach(el =>{
let type = "minus"; el.addEventListener("click", getItem(type));
});
You shouldn't be calling the functions when registering the event listeners.
Instead of:
let plus = document.querySelectorAll(".kaufen");
plus.forEach(el =>{
let type = "plus"; el.addEventListener("click", getItem(type));
});
let minus = document.querySelectorAll(".zurück");
minus.forEach(el =>{
let type = "minus"; el.addEventListener("click", getItem(type));
});
Do this:
let plus = document.querySelectorAll(".kaufen");
plus.forEach(el =>{
el.addEventListener("click", () => getItem("plus"));
});
let minus = document.querySelectorAll(".zurück");
minus.forEach(el =>{
el.addEventListener("click", () => getItem("minus"));
});
First of all I want to know if I am right about cause of the problem.
const updateScore = (isCorrect) => {
// Update Game Variables
if (isCorrect === true) {
counter++;
score += 100;
}
};
// Reset Styling
const resetLoadedQuestionStyling = (isCorrect) => {
questionScreen.style.display = 'none';
answerArr.forEach(answer => {
answer.classList.remove('correct');
answer.classList.remove('wrong');
answer.classList.remove('disable');
});
updateScore(isCorrect);
};
const styleAnswer = (div, isCorrect) => {
if (isCorrect === true) {
div.classList.add('correct');
} else {
div.classList.add('wrong');
for (let i = 0; i < answerArr.length; i++) {
if (i === currentQuestion.correct) {
answerArr[i].classList.add('correct');
}
}
}
// Prevent Second Check
answerArr.forEach(answer => {
answer.classList.add('disable');
});
// Reset Styling
setTimeout(() => {
resetLoadedQuestionStyling(isCorrect);
}, 3000);
};
const checkAnswer = (div, index) => {
const userChoice = index;
// Default Answer State
let isCorrect = false;
if (userChoice === currentQuestion.correct) {
isCorrect = true;
}
styleAnswer(div, isCorrect);
};
answerArr.forEach((div, index) => {
div.addEventListener('click', () => {
checkAnswer(div, index);
});
});
My counter updates 1,time, that 2 times... and I think the cause of this issue is that my EventListener is in a forEach loop, is that right?
How to prevent it?
Thanks!
EDIT: Addded more of the code in order to get my idea better.
EDIT: answerArr is array of 4 divs in my HTML
There may be a setTimeout-related issue. Every time an answer is clicked, the counter is set to be incremented after 3 seconds.
Here's the sequence when an answer is clicked:
'click'
checkAnswer ->
styleAnswer ->
setTimeout =>
resetLoadedQuestionStyling ->
updateScore ->
counter++
Below is the code with all of the unrelated lines removed. It does increment the counter after every click, but only after 3 seconds.
const answerArr = [...document.querySelectorAll('button')];
let counter = 0;
const span = document.getElementById('counter');
const updateScore = (isCorrect) => {
if (isCorrect === true) {
counter++
}
span.innerText = counter;
}
const resetLoadedQuestionStyling = (isCorrect) => {
updateScore(isCorrect)
}
const styleAnswer = (div, isCorrect) => {
// Reset Styling after 3 seconds
setTimeout(() => {
resetLoadedQuestionStyling(isCorrect);
}, 3000);
}
const checkAnswer = (div, index) => {
styleAnswer(div, true);
}
answerArr.forEach((div, index) => {
div.addEventListener('click', () => {
checkAnswer(div, index);
});
});
<button>Answer 1</button><br>
<button>Answer 2</button><br>
<button>Answer 3</button><br>
<button>Answer 4</button><br>
<p>Counter: <span id="counter"></span></p>
const form = document.getElementById("form");
let accountBalance = $("#accountBalance");
let stockPrice = $("#stockPrice");
accountBalance = parseInt(accountBalance);
stockPrice = parseFloat(stockPrice);
// const div = document.getElementById('div');
$("#display").hide();
let amountPerTrade = function amountPerTrade() {
return accountBalance / 4;
}
// Returns shares that are allowed per trade
let sharesPerTrade = function sharesPerTrade() {
const amountPerTrade = accountBalance / 4;
return Math.floor(amountPerTrade / stockPrice);
}
// Returns amount that should be calculated for limit and stop amounts
function getExitAmount(percentage) {
let amount = ((accountBalance * percentage) / sharesPerTrade()).toFixed(2);
return amount;
}
let limitPrice = function limitPrice() {
return getExitAmount(.03) + stockPrice;
}
let stopPrice = function stopPrice() {
return stockPrice - getExitAmount(.01);
}
let possibleProfit = function possibleProfit() {
return (getExitAmount(.03) * sharesPerTrade()).toFixed(2);
}
let possibleLoss = function possibleLoss() {
return (getExitAmount(.01) * sharesPerTrade()).toFixed(2);
}
$("form").submit(function () {
$("form").hide();
$("#amountPerTrade").html(amountPerTrade);
$("#sharesPerTrade").html(sharesPerTrade);
$("#limitPrice").html(limitPrice);
$("#stopPrice").html(stopPrice);
$("#possibleProfit").html(possibleProfit);
$("#possibleLoss").html(possibleLoss);
$("#display").show();
return false;
});
$("#reset").click(function (){
$("form").show();
$("#display").hide();
return false;
});
So this is my js code, all my id's in the HTML correspond. I've checked rechecked and checked again. I know I'm missing something stupid here. But every time I run it either nothing is put into the HTML element or I NaN.
The full code is at https://github.com/rustycomer/stock-strategy-calculator/tree/Update2.0
There are a number of problems in your code.
I have made some changes on it so the result can be shown now. You can have a check first.
const form = document.getElementById("form");
let accountBalance = $("#accountBalance")[0].value;
let stockPrice = $("#stockPrice")[0].value;
// const div = document.getElementById('div');
$("#display").hide();
let amountPerTrade = function amountPerTrade() {
return accountBalance / 4;
}
// Returns shares that are allowed per trade
let sharesPerTrade = function sharesPerTrade() {
let amountPerTrade = accountBalance / 4;
return Math.floor(amountPerTrade / stockPrice);
}
// Returns amount that should be calculated for limit and stop amounts
function getExitAmount(percentage) {
let amount = (((accountBalance) * percentage) / sharesPerTrade()).toFixed(2);
return amount;
}
let limitPrice = function() {
return getExitAmount(.03) + stockPrice;
}
let stopPrice = function() {
return stockPrice - getExitAmount(.01);
}
let possibleProfit = function() {
return (getExitAmount(.03) * sharesPerTrade()).toFixed(2);
}
let possibleLoss = function() {
return (getExitAmount(.01) * sharesPerTrade()).toFixed(2);
}
$("form").submit(function () {
$("form").hide();
accountBalance = parseInt(accountBalance[0].value);
stockPrice = parseInt(stockPrice[0].value);
$("#amountPerTrade").html(amountPerTrade());
$("#sharesPerTrade").html(sharesPerTrade());
$("#limitPrice").html(limitPrice());
$("#stopPrice").html(stopPrice());
$("#possibleProfit").html(possibleProfit());
$("#possibleLoss").html(possibleLoss());
$("#display").show();
return false;
});
$("#reset").click(function (){
$("form").show();
$("#display").hide();
return false;
});
The major problem of your code is that the variables or functions did not manipulate properly.
In your $("form").submit(function() { }), $(target).html() can receive the html code you want to insert but not the function you have declared. You need to execute those function to get the returned value for insertion.
Also, in line 2 to 3, you have to get the value from the input but not the $(target).
Finally, please be careful the differences between var, let and const. They can make you crazy if you use them incorrectly.
Good luck.
not sure ,but it run and i hv chg u code to my code style
const form = document.getElementById("form");
$("#display").hide();
$("form").submit(function ()
{
$("form").hide();
var accountBalance = $("#accountBalance").val();
var stockPrice = $("#stockPrice").val();
function amountPerTrade()
{
return accountBalance / 4;
}
// Returns shares that are allowed per trade
function sharesPerTrade()
{
//const amountPerTrade = accountBalance / 4;
//return Math.floor(amountPerTrade() / stockPrice);
return (amountPerTrade() / stockPrice);
}
// Returns amount that should be calculated for limit and stop amounts
function getExitAmount(percentage)
{
return ((accountBalance * percentage) / sharesPerTrade()).toFixed(2);
}
function limitPrice()
{
return getExitAmount(0.03) + stockPrice;
}
function stopPrice()
{
return stockPrice - getExitAmount(0.01);
}
function possibleProfit()
{
return (getExitAmount(0.03) * sharesPerTrade()).toFixed(2);
}
function possibleLoss()
{
return (getExitAmount(0.01) * sharesPerTrade()).toFixed(2);
}
accountBalance = parseInt(accountBalance);
stockPrice = parseFloat(stockPrice);
// const div = document.getElementById('div');
$("#amountPerTrade").html(amountPerTrade());
$("#sharesPerTrade").html(sharesPerTrade());
$("#limitPrice").html(limitPrice());
$("#stopPrice").html(stopPrice());
$("#possibleProfit").html(possibleProfit());
$("#possibleLoss").html(possibleLoss());
$("#display").show();
return false;
});
$("#reset").click(function (){
$("form").show();
$("#display").hide();
return false;
});