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);
}
}
Related
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);
}
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/
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)
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);
});
}
first of all i'm pretty new to JS.
i'm trying to make a memory game but i have the next problem.
the code :
function cardClicked(elCard) {
// If the user clicked an already flipped card - do nothing and return from the function
if (elCard.classList.contains('flipped')) {
return;
}
// Flip it
elCard.classList.add('flipped');
// This is a first card, only keep it in the global variable
if (elPreviousCard === null) {
elPreviousCard = elCard;
} else {
// get the data-card attribute's value from both cards
var card1 = elPreviousCard.getAttribute('data-card');
var card2 = elCard.getAttribute('data-card');
// No match, schedule to flip them back in 1 second
if (card1 !== card2) {
setTimeout(function () {
elCard.classList.remove('flipped');
elPreviousCard.classList.remove('flipped');
elPreviousCard = null;
}, 1000)
wrongPick.play();
} else {
// Yes! a match!
flippedCouplesCount++;
elPreviousCard = null;
rightPick.play();
}
}
i would like to prevent the user from clicking more then two times (it's a memory game.) can someone tell me how can i implement this into my code please?
You can set a global variable to isClickable initially set to true, enter the code check if its true, if it isn't, return, else go ahead and set it to false and do a timeout to set it to true again, like:
var isClickable = true;
function cardClicked(elCard) {
if (!isClickable) return;
isClickable = false;
setTimeout(function () {
isClickable = true;
}, 500)
...
Since it's a card game I would do the following:
Make array of elements:
var cards = (
{
"card":"numberOfCard",
"isclicked" :"yes/no"
}
);
And then every time somebody clicks on card I would change isClickable to no so next time event occures I would prevent it.
create variable for example opened_cards that store how many card opened, if less than 2 allow open another card else do nothing.
var opened_cards = 0;
function cardClicked(elCard) {
// do check here
if (opened_cards < 2) {
// less than 2 card opened do operation
opened_cards++;
if (elCard.classList.contains('flipped')) {
return;
}
// Flip it
elCard.classList.add('flipped');
// This is a first card, only keep it in the global variable
if (elPreviousCard === null) {
elPreviousCard = elCard;
}
else {
// get the data-card attribute's value from both cards
var card1 = elPreviousCard.getAttribute('data-card');
var card2 = elCard.getAttribute('data-card');
// No match, schedule to flip them back in 1 second
if (card1 !== card2) {
setTimeout(function() {
opened_cards -= 2;
elCard.classList.remove('flipped');
elPreviousCard.classList.remove('flipped');
elPreviousCard = null;
}, 1000);
wrongPick.play();
}
else {
// Yes! a match!
opened_cards = 0;
flippedCouplesCount++;
elPreviousCard = null;
rightPick.play();
}
}
}
}