if statement not executing action even though condition is met - javascript

I'm trying to change the class of an element based on some conditions.
const pwnButtonHidden = document.querySelector(".pwn-button-hidden");
let condition = 0;
for (let idNumber = 1; idNumber < 13; idNumber++) {
setTimeout(() => {
document
.getElementById(`btn-${idNumber}`)
.addEventListener("click", (e) => {
condition++;
console.log(condition);
document.getElementById(`product-${idNumber}`).className =
"product-fake";
document.getElementById(`btn-${idNumber}`).disabled = true;
document
.getElementById(`btn-${idNumber}`)
.removeEventListener("mouseenter", selectSfx, true);
});
if (condition >= 12) {
pwnButtonHidden.className = "pwn-button";
}
}, 4000);
}
As you can see, at every click condition is augmented by 1. However, even when it reaches 12 (verified by console.log(condition)), it doesn't trigger the class change. How can I fix this?
Tried changing the number of the condition.

Testing the condition is happening outside of the click event handler. So it's only being checked one time for each loop iteration right when the 4 second delay times out. The code is relocated below.
...
.removeEventListener("mouseenter", selectSfx, true);
if (condition >= 12) {
pwnButtonHidden.className = "pwn-button";
}
});
}, 4000);
}

Related

After I changed ID Javascript, not working next "click" event, what is the problem?

let x = ["1", "3", "5"]
$("#button").click(
function num() {
$("#answers").html(x[0])
document.getElementById("button").setAttribute("id", "button2");
}
)
$("#button2").click(
function num2() {
$("#answers").html(x[1])
document.getElementById("button").setAttribute("id", "button3");
}
)
$("#button3").click(
function num3() {
$("#answers").html(x[2])
}
)
When you have this:
$("#button2").click(.......
... that will look at #button2 right now, not at some future renaming. Since at the start there is no such id, this .click method is not doing anything.
You can achieve this with event delegation, but in your case I would go for a different solution.
Changing the id attribute of a DOM element is really bad practice. Instead use a variable which will determine in which "case" you are, and just use one click handler where you inspect that variable. Something like this:
var state = 1;
$("#button").click(function num() {
if (state == 1) {
$("#answers").html(x[0]);
state = 2; // move to the next state..
} else if (state == 2) {
// do something else...
state = 3;
} else if (state == 3) {
// ... etc ...
}
})
If the logic is really so simple that you want to just display the next entry in the x array, then let the state be that index:
var index = 0;
$("#button").click(function num() {
$("#answers").html(x[index]);
index = (index+1) % x.length; // round robin selection of array value
})
Just add current index and your code will be simple:
let x = ["1","3","5"]
let currentIndex = -1
$("#button").click(() => {
currentIndex += 1
$("#answers").html(x[currentIndex])
}
)
See in playground: https://jsfiddle.net/denisstukalov/x0sq6fry/6/

When boolean turns false, check 5 seconds if it will turn back to true, else do some action

I have in NodeJS a variable that updates every second. I want to monitor it to see if it turns below a certain threshold (e.g. 1000).
If it does go below the threshold, it should wait 5 seconds and monitor if the variable goes back above again. If not, it should return a function. If it does go above, it can stop the times and start monitoring again.
Can't get any code to work.
Not sure if the code below is even in the right direction..!
var waitedSoFar = 0;
var imageDisplayed = CheckIfImageIsDisplayed(); //this function is where you check the condition
while(waitedSoFar < 5000)
{
imageDisplayed = CheckIfImageIsDisplayed();
if(imageDisplayed)
{
//success here
break;
}
waitedSoFar += 100;
Thread.Sleep(100);
}
if(!imageDisplayed)
{
//failed, do something here about that.
}
You could have a function that observe and wrap this variable that change so often. Something as simple as
function observeValue(initialValue) {
let value = initialValue
let clearEffects = []
let subscribers = []
return {
value: () => value,
change(val) {
clearEffects.forEach(oldEffect => oldEffect && oldEffect())
value = val
clearEffects = subscribers.map(subscriber => subscriber(value))
},
subscribe(listener) {
subscribers.push(listener)
}
}
}
is generic enough. The function returns three methods:
one to get the current value
one to change the value
on to subscribe on every value change
I would suggest to leverage the last one to monitor and trigger any side effects.
You can use it like this:
const monitor = observeValue(true)
monitor.subscribe((value) => {
if (value !== false) {
return
}
const timeout = setTimeout(() => {
console.log('value was false for five seconds')
}, 5000)
return () => {
clearTimeout(timeout)
}
})
and somewhere else you can change the value with
monitor.change(false)

pre post condition on javascript?

I have a single timer button which showing start and stop. When I click it, the text changed to stop, and when I click it again then the text changed to start. To maintain the state, then I wrote a code like this:
start.onclick = function() {
if (state == 0) {
state = 1;
timer();
}
if (state == 1) {
state = 0;
clearTimeout(t);
}
}
Pre-condition of state is 0. On normal case, it should work if state equals 0, then state will changed to 1 and timer() will be executed. If state equals 1, state will changed to 0 and clearTimeout() will be executed. But I don't know why it won't work like this in javascript. Then I change the code like this:
start.onclick = function() {
if (state == 0) {
timer();
}
if (state == 1) {
state = 0;
clearTimeout(t);
}
state = 1;
}
Then it worked, timer() is executed and state changed to 1, but when I tried again to start the button, then nothing worked. I check the state, then the state is in 1. because the second condition is not executed. is anyone know what wrong with this code? what am I missing?
Your code sets the state to 1, if it was 0.
This makes the condition in second if true, hence its code is also executed. Hence both ifs are executed when state is 0.
Use else if like
start.onclick = function () {
if (state == 0) {
state = 1;
timer();
} else if (state == 1) { <=== see the difference in this line
state = 0;
clearTimeout(t);
}
}

How can I set timers in slideshow to show as selected?

I have to create a slideshow, using an array of images and have that set on a timer. There is a drop-down menu with slow, medium, and fast options and the pictures need to transition with accordance to the drop down option selected. Whenever I execute this code in a web browser the code repeats itself, while doubling, as I read the value of i in the console.
I have tried using a while and a do-while loop to have the images on a rotation.
I have also tried putting the if-statements outside and below/above the function.
<script>
var i = 0;
function changeImg(){
if (x == 'slow'){
setInterval("changeImg()", 5000);
} else if (x == 'medium'){
setInterval("changeImg()", 3000);
} else if (x == 'fast') {
setInterval("changeImg()", 1000);
} else {}
while (i < 3){
console.log(i);
document.slide.src = sportsArray[i];
i++;
}
console.log(i);
console.log(sportsArray);
}
</sctipt>
First, I would read up on MDN's docs on setInterval() and clearInterval to fill in the knowledge gaps that lead you to approach the problem this way.
You are recursively calling changeImg() in your code which I believe is causing the issue you describe as:
the code repeats itself, while doubling, as I read the value of i in the console
Also, your while loop will run immediately when calling changeImg() which also does not appear to be desired in this situation.
setInterval() mimics a while loop by nature. There is no need for a while loop in this code. Below is a solution that I hope you can use as a reference. I separated the code to determine the interval into a function the getIntervalSpeed.
function changeImg(x) {
var getIntervalSpeed = function(x) {
if (x === 'slow') {
return 5000;
} else if (x === 'medium') {
return 3000;
} else if (x === 'fast') {
return 1000;
} else {
return 3000;
// return a default interval if x is not defined
}
};
var i = 0;
var slideShow = setInterval(function() {
if (i >= sportsArray.length) {
i = 0; // reset index
}
document.slide.src = sportsArray[i]; // set the slide.src to the current index
i++; // increment index
}, getIntervalSpeed(x));
// on click of ANY button on the page, stop the slideshow
document.querySelector('button').addEventListener('click', function() {
clearInterval(slideShow);
});
}

Javascript Click Event Pushing Multiple Duplicates to Array

In recreating the Simon game, I am trying to push a click event to an array and then immediately test that Array in a nested function. On the first pass it seems to work.
However, on the third run the array does not seem to clear.
The screen shot below also shows that each input is printed multiple times to the console.
Full code pen here - https://codepen.io/jhc1982/pen/NwQZRw?editors=1010
Quick example:
function userMoves() {
var userInput = [];
document.getElementById("red").addEventListener("click", function(){
userInput.push("red");
testington();
});
$(".red").mousedown(function(event){
redAudio.play();
$(".red").css("background-color", "red");
});
$(".red").mouseup(function(){
$(".red").css("background-color", "#990000");
});
function testington(){
if (userInput.length == pattern.length) {
for (var i = 0; i < userInput.length; i++) {
if (userInput[i] !== pattern[i]) {
alert("Game Over");
} else if (i === userInput.length -1 && userInput[i] === pattern[i]) {
userInput = emptyArr;
simonMoves();
console.log("user input is ",userInput);
} else {
continue;
}
}
}
}
}
I am sure it is something really obvious but have been stuck for hours.
I think the problem may be that you are assigning the click events every time the userMoves execute. That means every time the function is called the event is added to the elements, so after two calls to userMoves() when you click on red the event is executed twice, after three calls it is executed three times, etc.
The code that adds the event listener should be out of the userMoves function. The testington function should also be out of userMoves, which would get much simpler:
function userMoves() {
$("#score-text").text(level);
userInput = [];
}
Here's a Pen with working code: https://codepen.io/anon/pen/ppzqyY
You need to add the break; keyword to after alert("Game over");
function testington(){
if (userInput.length == pattern.length) {
for (var i = 0; i < userInput.length; i++) {
if (userInput[i] !== pattern[i]) {
alert("Game Over");
break; // Break the loop
} else if (i === userInput.length -1 && userInput[i] === pattern[i]) {
userInput = emptyArr;
simonMoves();
console.log("user input is ",userInput);
} else {
continue;
}
}
}
}

Categories

Resources