This question already has an answer here:
How do I stop requestAnimationFrame
(1 answer)
Closed 6 years ago.
I'm using HTML Canvas. I want new frames to be requested only if the click function hasn't been fired again. Basically I want it to "stop" the previous recursiveness, I think
document.addEventListener('click', function(){
[...]
var animate = function() {
if (the click event was NOT fired again) {
requestAnimationFrame(animate);
}
};
animate();
});
How would I do this?
You can set a global variable like rafId and in the line you invoke rAF make it like;
rafId = requestAnimationFrame(animate);
then when needed invoke cancelAnimationFrame() like cancelAnimationFrame(rafId)
Related
This question already has answers here:
JavaScript while mousedown
(3 answers)
Closed 4 years ago.
I need to execute a javascript function continuosly (every second or half a second for example), but this needs to happen while a button is pressed.
I tried with the following:
$("#buttonID").bind('touchstart',function(event){
setInterval(function() {
FUNCTION
}, 1000);
});
It is not working that way, using "mousedown" either.
What it's answered on question JavaScript while mousedown
did not solve my issue, so I don't consider this question as a duplicate.
Is there a beginner's mistake and I'm not seeing it? what do you suggest?
You have to capture a reference to the timer and cancel it when the mouse is released.
var timer = null; // Will hold a reference to the timer
$("#buttonID").on('mousedown',function(event){
// Set the timer reference
timer = setInterval(function() {
console.log("Function running");
}, 1000);
});
$("#buttonID").on('mouseup',function(event){
clearInterval(timer); // Cancel the timer
console.log("Timer cancelled.");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="buttonID">Hold me down to run function!</button>
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
very new to JS and just playing around with examples I have written from a book.
With the code below - why are my functions not being executed? I am calling them and the syntax is correct. If I place document.addEventListener ("DOMContentLoaded" , init , false) ;
then the init() function will execute but not the test() function.
I am also confused as to where the document.addEventListener should be placed normally and exactly what it means with regards to the init function. Should the init() function always be called first? What normally goes in an init()function?
Thanks in advance. Code below ;
function init() {
var panel = document.getElementById("panel");
panel.innerHTML = "Hello World";
}
function test() {
var panel = document.getElementById("panel");
panel.innerHTML = "See ya";
}
init();
test();
You are probably executing the functions before the DOM elements have been loaded. The page is read from top to bottom. If the function executes before the HTML is read, the element won't exist.
Many developers make the script the last element in the body to avoid this.
Or use an onload handler, like this
window.onload = function () {
init();
test();
}
The functions do not need to be defined in the handler
EDIT. It is also true that you are writing data to the same element, so only the second function will have a result you can see. You can write to a separate element, or do as one answer suggests and add the data together.
It sounds like the methods are being called, but they are raising errors because they are called before the DOM is finished loading. Under normal circumstances, script like this will be executed as soon as the browser reaches it, so if this happens before the DOM is loaded (which is usually the case), the calls to document.getElementById() will fail because the document hasn't been loaded.
You're close with your call to document.addEventListener ("DOMContentLoaded" , init , false); - this tells the browser to call init when the DOM has been loaded. However, you're only calling init in this case, so test() doesn't get called.
I would suggest removing your inline calls to init(); and test();, then adding the following:
function onLoaded(){
init();
test();
}
and then calling onLoaded from your event listener:
document.addEventListener ("DOMContentLoaded" , onLoaded , false);
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I need to be able to cancel an event based on the amount of time an element is hovered on. Say when I set the delay to 500ms, when the element is being hovered on for less than that, an event should be cancelled, otherwise it is fired. The delay() and setTimeout() function seem incapable of doing that.
You can try something like this instead of using jQuery delay method.
Working demo
var timeoutId = null;
$("selector").hover(function(){
if(timeoutId)
clearTimeout(timeoutId);
timeoutId = setTimeout(function(){
alert("do your stuff here");
}, 5000);
}, function(){
clearTimeout(timeoutId);
});
Someone might come up with something cleaner but the code below will be able to handle what you are asking. It requires 500 milliseconds to pass before the code inside the event can be triggered again. Could probably clean it up so that timer/delayMet aren't potentially global variables.
I'm using $('a').click as an example selector and event.
var timer,
delayMet = true;
$('a').click(function () {
if(delayMet === true) {
// your code here
}
else {
delayMet = false;
setTimeout(function () {
delayMet = true;
}, 500);
}
});
You can cancel setTimeout() by doing the following.
var timer = setTimeout(function(){...},5000);
...
clearTimeout(timer);
From jQuery .delay() docs:
The .delay() method is best for delaying between queued jQuery
effects. Because it is limited—it doesn't, for example, offer a way to
cancel the delay—.delay() is not a replacement for JavaScript's native
setTimeout function, which may be more appropriate for certain use
cases.
Not sure if that is what you mean though.
I have a jQuery slider on my site and the code going to the next slide is in a function called nextImage. I used setInterval to run my function on a timer, and it does exactly what I want: it runs my slides on a timer. BUT, if I go to the site in Chrome, switch to another tab and return, the slider runs through the slides continuously until it 'catches up'. Does anyone know of a way to fix this. The following is my code.
setInterval(function() {
nextImage();
}, 8000);
How to detect when a tab is focused or not in Chrome with Javascript?
window.addEventListener('focus', function() {
document.title = 'focused';
},false);
window.addEventListener('blur', function() {
document.title = 'not focused';
},false);
To apply to your situation:
var autopager;
function startAutopager() {
autopager = window.setInterval(nextImage, 8000);
}
function stopAutopager() {
window.clearInterval(autopager);
}
window.addEventListener('focus', startAutopager);
window.addEventListener('blur', stopAutopager);
Note that in the latest version of Chromium, there is either a bug or a 'feature' which is making this less reliable, requiring that the user has clicked at least once anywhere in the window. See linked question above for details.
I post an answer here: How can I make setInterval also work when a tab is inactive in Chrome?
Just do this:
setInterval(function() {
$("#your-image-container").stop(true,true);
nextImage();
}, 1000);
inactive browser tabs buffer some of the setInterval or setTimeout functions.
stop(true,true) - will stop all buffered events and execute immadietly only last animation.
The window.setTimeout() method now clamps to send no more than one timeout per second in inactive tabs. In addition, it now clamps nested timeouts to the smallest value allowed by the HTML5 specification: 4 ms (instead of the 10 ms it used to clamp to).
A few ideas comes to mind:
Idea #1
You can make it so that a short burst is idempotent. For example, you could say:
function now() {
return (new Date()).getTime();
}
var autopagerInterval = 8000;
function startAutopager() {
var startImage = getCurrentImageNumber();
var startTime = now();
var autopager = setInterval(
function() {
var timeSinceStart = now() - startTime();
var targetImage = getCurrentImageNumber + Math.ceil(timeSinceStart/autopagerInterval);
if (getCurrentImageNumber() != targetImage)
setImageNumber(targetImage); // trigger animation, etc.
},
autopagerInterval
);
return autopager;
}
This way even if the function runs 1000 times, it will still run in only a few milliseconds and animate only once.
note: If the user leaves the page and comes back, it will have scrolled. This is probably not what the original poster wants, but I leave this solution up since it is sometimes what you want.
Idea #2
Another way to add idempotence (while still keeping your nextImage() function and not having it scroll to the bottom of the page) would be to have the function set a mutex lock which disappears after a second (cleared by another timeout). Thus even if the setInterval function was called 1000 times, only the first instance would run and the others would do nothing.
var locked = false;
var autopager = window.setInterval(function(){
if (!locked) {
locked = true;
window.setTimeout(function(){
locked=false;
}, 1000);
nextImage();
}
}, 8000);
edit: this may not work, see below
Idea #3
I tried the following test:
function f() {
console.log((new Date()) + window.focus());
window.setTimeout(f, 1000);
}
f();
It seems to indicate that the function is being called every second. This is odd... but I think this means that the callbacks are being called, but that the page renderer refuses to update the page in any graphical way while the tab is unfocused, delaying all operations until the user returns, but operations keep piling up.
Also the window.focus() function doesn't say if the window has focus; it GIVES focus to the window, and is thus irrelevant.
What we want is probably this: How to detect when a tab is focused or not in Chrome with Javascript? -- you can unset your interval when the window loses focus (blur), and reset it when it gains focus.
I don't know exactly what is going on in your function nextImage(), but I had a similar issue. I was using animate() with setInterval() on a jQuery image slider that I created, and I was experiencing the same thing as you when I switched to a different tab and back again. In my case the animate() function was being queued, so once the window regained focus the slider would go crazy. To fix this I just stopped the animate() function from queuing.
There are a couple ways you can do this. the easiest is with .stop(), but this issue and ways to fix it are documented in the jQuery docs. Check this page near the bottom under the heading additional notes: http://api.jquery.com/animate/
I had faced similar issue, somehow this code below works fine for me.
var t1= window.setInterval('autoScroll()', 8000);
window.addEventListener('focus', function() {
focused = true;
window.clearInterval(t1);
t1 = window.setInterval('autoScroll()', 8000);
},false);
window.addEventListener('blur', function() {
focused = false;
window.clearInterval(t1);
},false)
function autoScroll()
{
if ( running == true){
if ( focused = true){
forwardSlide();
}
}
else {
running = true;
}
}
If you are using Soh Tanaka's image slider then just add this...to solve your Google Chrome issue:
$(".image_reel").stop(true, true).fadeOut(300).animate({ left: -image_reelPosition}, 500 ).fadeIn(300);
Take note of the .stop() function. Ignore the fading in and out stuff, that's what I used on my version
Thanks
Seconding the comment by jgerstle to use page visibility events instead, see https://www.w3.org/TR/page-visibility/#example-1-visibility-aware-video-playback for more around subscribing to 'visibilitychange' for hidden/visible states.
This seems to be more useful than focus/blur these days as it covers visible-but-not-selected windows if concerned also about multi-window operating systems.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
javascript: pause setTimeout();
Im using jQuery and working on a notification system for my site. The notifications automatically fadeout using the setTimeout function.
How can i stop the timer of the setTimeout call?
For example i would like to pause the setTimeout call while the mouse is over the notification and continue the count down mouseout...
I googled "pause setTimeout" with no luck.
Im currently clearing the setTimeout call with clearTimeout and at same time fading out the notification on mouseout but it would be nice to have that pause effect.
Any ideas?
Try this.
var myTimeOut;
$(someElement).mouseout( function () {
myTimeOut = setTimeout("mytimeoutfunction()", 5000)
});
$(someElement).mouseover( function () {
clearTimeout(myTimeOut);
});
It wouldn't be too hard to add a PausableTimeout class:
(Might not be valid JS, but it shouldn't be too hard to get it working):
function PausableTimeout(func, millisec) {
this.func = func;
this.stTime = new Date().valueOf();
this.timeout = setTimeout(func, millisec);
this.timeLeft = millisec;
}
function PausableTimer_pause() {
clearTimeout(self.timeout);
var timeRan = new Date().valueOf()-this.stTime;
this.timeLeft -= timeRan;
}
function PausableTimer_unpause() {
this.timeout = setTimeout(this.func, this.timeLeft);
this.stTime = new Date().valueOf();
}
PausableTimer.prototype.pause = PausableTimer_pause;
PausableTimer.prototype.unpause = PausableTimer_unpause;
//Usage:
myTimer = new PausableTimer(function(){alert("It works!");}, 2000);
myTimer.pause();
myTimer.unpause();
Of course, it'd be a great idea to add some error checking in there (don't want it to be possible to unpause the timeout multiple times and end up with hundreds of timeouts!), but I'll let that be your job :P
Use clearTimeout() on mouseover event and use setTimeout() again on mouseout event.
http://www.w3schools.com/jsref/met_win_cleartimeout.asp