I've been trying to properly use setTimeOut but haven't been able to figure it out.
Expected Output:
if you click any button, a banner will slide into view, after 8 seconds it will disappear.
click anywhere else on the page and the banner disappear.
click the same button before the 8 seconds timer ends and a new 8 should start.
Actual output:
if you click any button a banner will slide into view, after 8 seconds it will disappear.
click anywhere on the page so the banner disappear.
click the same button before the 8 seconds timer ends, instead of starting a new 8-seconds the banner will finish off the remaining seconds of the first click then disappear.
Here is what I've tried and also a codesandbox:
[a link] https://codesandbox.io/s/n7zvwn11yj
const getGreetingBanner =(e)=>{
let query = document.querySelector(e)
query.style.right = '8px';
let timer = setTimeout(() => {
query.style.right = '-165px';
}, 8000);
clearTimeOut(timer)
}
document.addEventListener('click', (e) => {
let triggeredElement = e.target.className;
if (triggeredElement === 'container') {
document.querySelectorAll('.banishBanner').forEach(function(x) {
x.style.right = '-180px';
})
}
})
HTML:
<div class="container">
<button onclick="getGreetingBanner('.thankyou')" type="button" class="accept">Accept</button>
<button onclick="getGreetingBanner('.comeBackSoon')" type="button" class="cancel">Cancel</button>
<div class="banishBanner thankyou">Thank You!</div>
<div class="banishBanner comeBackSoon">Come back soon.</div>
</div>
You must clear timeout when you clicking again on same button.
var timeout;
const getGreetingBanner =(e)=>{
let query = document.querySelector(e)
query.style.right = '8px';
//clearing timeout
clearTimeout( timeout );
timeout = setTimeout(() => {
query.style.right = '-165px';
}, 8000);
}
Related
I am trying to add a feature to my game where an img appears after a set amount of time. The is only displayed for a set time before it disappears again or until it is clicked.
Here is my code below but it doesn't work because the clearInterval is ending the disappear function before it executes. But without it, the timer continues and the image appears and disappears at the same time.
How would I make it so the image stays for 5 seconds, then disappears again, then next time the image appears it stays for 5 seconds again?
const bunnyRocket = document.getElementById('bunny-rocket');
bunnyRocket.hidden = true;
bunnyRocket.addEventListener('click', () => {
console.log('You got it');
player.carrots += 1000;
bunnyRocket.hidden = true;
})
const rocketAppear = setInterval(bunnyRocketAppear, 5000);
function bunnyRocketAppear() {
let disappear = setInterval(() => {
console.log('DISAPPEAR');
bunnyRocket.hidden = true;
}, 5000)
console.log('SHOULD APPEAR NOW');
bunnyRocket.hidden = false;
clearInterval(disappear);
}
Your bunny appears every 5 seconds but also disappears after 5 seconds. You might want to make your bunny disappear before he appears again (e.g make him disappear after 3s).
Additionally, since the bunny only disappears once for every time he appears, you'd want your second interval to be a timer instead
const bunnyRocket = document.getElementById('bunny-rocket');
bunnyRocket.hidden = true;
bunnyRocket.addEventListener('click', () => {
console.log('You got it');
player.carrots += 1000;
bunnyRocket.hidden = true;
})
const rocketAppear = setInterval(bunnyRocketAppear, 5000);
function bunnyRocketAppear() {
//everytime he appears, set a timeout to make him disappear after 3s
let disappear = setTimeout(() => {
console.log('DISAPPEAR');
bunnyRocket.hidden = true;
}, 3000)
console.log('SHOULD APPEAR NOW');
bunnyRocket.hidden = false;
//If we do clearTimeout(disappear), the bunny won't disappear :(
}
I'm trying to show a label when a user clicks a button. I've tried to use setTimeout to achieve this, but when you click the button multiple times before the timeout ends, this don't work properly.
This is what I got:
const [cameraLabelVisible, setCameraLabelVisible] = useState(false);
let labelTimer;
function labelVisible() {
setCameraLabelVisible(true);
labelTimer = setTimeout(() => {
setCameraLabelVisible(false);
clearTimeout(labelTimer);
}, 1500);
}
};
My question is: Is it posible reset the timer to the initial value (in this case 1500) by clicking the same button before the timer ends?
I want to show the label if the button is clicked multiple times before the time runs out.
You could clear the existing timer first:
const [cameraLabelVisible, setCameraLabelVisible] = useState(false);
let labelTimer;
function labelVisible() {
setCameraLabelVisible(true);
// clear the timer if there's another timer running
if(labelTimer) clearTimeout(labelTimer);
labelTimer = setTimeout(() => {
setCameraLabelVisible(false);
}, 1500);
}
My question is: Is it possible reset the timer to the initial value
(in this case 1500) by clicking the same button before the timer ends?
Yes, this can be achieved by clearing the existing timeout and creating a new timeout. This can be achieved as below:
const [cameraLabelVisible, setCameraLabelVisible] = useState(false);
let labelTimer;
function labelVisible() {
if(labelTimer) {
clearTimeout(labelTimer);
}
setCameraLabelVisible(true);
labelTimer = setTimeout(() => {
setCameraLabelVisible(false);
clearTimeout(labelTimer);
}, 1500);
}
};
I want to show the label if the button is clicked multiple times
before the time runs out.
This sounds like a different issue than what you asked above. If I'm understanding you correctly, the below will allow you to click the button multiple times within 1.5 seconds, and the label appear for only that amount of time before clearing.
const [cameraLabelVisible, setCameraLabelVisible] = useState(false);
let labelTimer = undefined;
function labelVisible() {
setCameraLabelVisible(true);
if(!labelTimer) {
labelTimer = setTimeout(() => {
setCameraLabelVisible(false);
labelTimer = undefined;
}, 1500);
}
};
I wish to allow this JavaScript Button to show other page (active) only when it was continuously clicked for 10 second. Any help would be highly appreciated. e.g. if it was clicked for less than 10 second, it shouldn't call the function and nothing happens.
function callAnothePage()
{
window.location = "https://www.bbc.com/";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!doctype html>
<html class="no-js" lang="">
<body>
<button name="buttonClick" class="button" onclick="callAnothePage()"
id="btnMakeCall" >how</button>
</body>
</html>
The clue is to use onmouseup and onmousedown instead of onclick. That way you can start a timeout when the user clicks and remove it again when they stop clicking.
const button = document.querySelector( 'button' );
let timeout = null;
button.addEventListener( 'mousedown', event => {
timeout = setTimeout(() => {
console.log( '2 sec passed' );
}, 2000 );
});
button.addEventListener( 'mouseup', event => {
if ( timeout ) clearTimeout( timeout );
});
<button>2 sec</button>
If you want the user to click and hold the button for some time the answer of Shilly is a good solution.
But if you want the user to press the button again and again until the time end, maybe you should use a hit ratio instead.
With hit ratio you could define a good ratio to redirect the user and challenge the user to go over the ratio.
That way the user will click repeatedly in the button over a period of time (10 seconds) and you compare the user hit ratio (times clicked / time) with your defined ratio.
The code is something like the snippet below:
document.addEventListener("DOMContentLoaded", function() {
var button = document.querySelector("button#clickMe");
var clicks = 0;
var hitRateNeeded = 3.2;
var timeInSeconds = 10;
var started = false;
var timeout = null;
button.addEventListener('click', function() {
if (!started) {
started = true;
timeout = setTimeout(function() {
freeze();
clearAttempt();
// do something ...
}, timeInSeconds * 1000);
}
clicks++;
});
function freeze() {
var currentHitRate = clicks / timeInSeconds;
console.log("Current Hit Rate", currentHitRate);
console.log("Passed?", currentHitRate > hitRateNeeded)
}
function clearAttempt() {
clicks = 0;
started = false;
clearTimeout(timeout);
}
});
<button id="clickMe">Click for 10 seconds</button>
I'm learning event phasing of nested elements so I create small project. Codepen JS starts on 43rd line.
So here's simple nested divs.
<div id="zzz" class="thir">
0
<div id="xxx" class="thir">
0
<div id="sss" class="thir">
0
</div>
</div>
</div>
And here what we do with them.
const ar2 = [zzz, xxx, sss];
ar2.map(e => {
e.addEventListener('click', nestedClick, phase);
})
function nestedClick(e) {
// e.stopPropagation();
const meow = this;
const prevColor = this.style.backgroundColor;
this.style.backgroundColor = '#757575';
window.setTimeout(() => { meow.style.backgroundColor = prevColor}, 500);
}
To visually show how capturing/bubbling works I'd like to change background color and set timeout on each step, wait until it's done and trigger next click with the same strategy.
But here I see after I click on any element event still goes through, changing color and forces all .setTimeout() like at the same time. How can I repair it?
Side question: why e.stopPropagation() works whether it's capturing or bubbling phase?
Thank you for attention!
You need to shift the start time of the timers. And for a flashing effect having a second timer would be good.
let counter = 1;
const ar2 = [...document.getElementsByClassName('thir')];
ar2.map(e => {
e.addEventListener('click', nestedClick);
e.addEventListener('mouseup', function() {
counter = 1;
});
});
function nestedClick(e) {
const prevColor = this.style.backgroundColor;
debugger;
setTimeout( () => {
this.style.backgroundColor = '#757575';
setTimeout( () => {
this.style.backgroundColor = prevColor;
}, 50 * (counter++));
}, 500 * (counter++));
}
<div id="zzz" class="thir">
CLICK ME
<div id="xxx" class="thir">
CLICK ME
<div id="sss" class="thir">
CLICK ME
</div>
</div>
</div>
I have a button inside a modal that have a countdown, at first it is disabled (is true), but after the countdown it turns disable.
If I leave the button countdown untill the end, and then I test it again (closing my modal and open it again), it starts the countdown over again, it works fine up to now.
But it has a strange bug.
If in the middle of the countdown, I close the modal and then open it again, my countdown restarts but it goes imedially to the end of the countdown, it doesn't go through all the numbers.
Here is my code:
html:
<button
ng-click="wizardCtrl.callModal()"
id="btn-unblock"
ng-disabled="wizardCtrl.unblock"
type="button"
class="btn btn-medium #{{ wizardCtrl.btn }}"
href=""
>
Wait #{{wizardCtrl.message}} seconds
</button>
controller:
vm.unblock = true;
function unblockButton() {
debugger;
vm.c = 5;
vm.message = vm.c;
var timer = $interval(function() {
vm.message = vm.c;
vm.c--;
if(vm.c<0) {
$interval.cancel(timer);
vm.unblock = false;
angular.element('#btn-unblock').text("Desbloquear e Ver");
vm.btn = "btn-green";
}
}, 1000);
}
When closing the modal, you should also abort the interval. It is still running when you open the modal up again, so it will affect the second modal. Alternatively check if an interval is set and clear it before opening.
You need to reset the timer and the button before you start the timer.
vm.unblock = true;
// Make your timer variable global
var timer = null;
function unblockButton() {
debugger;
vm.c = 5;
vm.message = vm.c;
// Clear old timer
$interval.cancel(timer);
// Block the button
vm.unblock = true; // Check this part of code...
vm.btn = "btn-red"; // This too...
// Start new timer
timer = $interval(function() {
vm.message = vm.c;
vm.c--;
if(vm.c<0) {
$interval.cancel(timer);
vm.unblock = false;
angular.element('#btn-unblock').text("Desbloquear e Ver");
vm.btn = "btn-green";
}
}, 1000);
}