Jquery setInterval too fast when coming from another tab - javascript

I've got a site with endlessly sliding images using jquery's setIntervall() function.
When calling the page in Chrome 13 and I switch to another tab to come back a few seconds later the image sliding is happening faster, as if it tried to keep up to where it was if it hadn't switched to another tab.
How could I resolve this issue?
$(window).load(function() {
setInterval(nextSlide, 3500);
});
function nextSlide(){
offset += delta;
$("#slideContent").animate({left: -1 * offset}, 1000);
}

At the beginning I would like to apologize for all the mistakes - my English is not perfect.
The solution of your problem may be very simple:
$(window).load(function() {
setInterval(nextSlide, 3500);
});
function nextSlide(){
offset += delta;
$("#slideContent").stop(true,true).animate({left: -1 * offset}, 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.
This problem will also appears in Firefox > 5.0 - read this article: Firefox 5 - changes
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).
here you can read, how animate works - it fires setInterval function many times. How animate really works in jQuery

The latest versions of Chrome apparently slow down the operation of setInterval when a tabbed page is in the background and then when you bring that page forward it tries to catch up.
On the Chromium blog, Google said:
In the forthcoming Chrome 11 release, we plan to reduce CPU consumption even for pages that are using setTimeout and setInterval. For background tabs, we intend to run each independent timer no more than once per second. This change has already been implemented in the Chrome dev channel and canary builds.
Your interval is 3.5 seconds, but the animation itself may be using much shorter timers.
Possible ways to work-around it:
Stop your timer/animation when the window is not visible. Restart the timer/animation when the window becomes visible.
Instead of setInterval, use setTimeout and then just reset the setTimeout each time it fires to create your own repeating interval - though in your case, it may be jQuery's use of timers that are the issue - I don't know.
Slow your timers down so they don't run afoul of this (again might be inside of jQuery not your own timers).
The best option is probably to figure out when to just stop and then restart the animation.
Similar question here: Chrome: timeouts/interval suspended in background tabs?.
FYI, Chrome has new experimental API for detecting page visibility for just this reason. You can read about it here: http://code.google.com/chrome/whitepapers/pagevisibility.html. it helps solve the issue when your page is visible, but doesn't have focus.

Hey are you using Jquery 1.6?
This may be the cause since 1.6 uses requestAnimationFrame for animations.
You may want to check this page out for a replacement for setInterval, clearInterval
http://blog.blenderbox.com/2011/06/24/jquery-1-6-1-and-setinterval/
code:
https://gist.github.com/1002116 [edit: updated source, edit2: currently doesnt work with firefox due to firefox bug. -- I had do downgrade to JQuery 1.5]
From the blogger:
Then, where you were calling setInterval(func, poll), you now call
requestInterval(func, poll). Where you call clearInterval(interval),
you now call clearRequestInterval(interval);

Have you tried not using setInterval or setTimeout at all, but just use the complete function of the animate function to kick off the next slide? The delay function is set to 2500 ( i.e. 1000 for the animate subtracted from the 3500 of the setInterval). I haven;t tried this with Chrome, so please let me know if it works.
var slider = function(n){
$("#slideContent").delay(2500).animate({left: -1 * n * delta},
1000,
function(){slider(n+1)}
);
};
slider(1);

try setInterval() it works
<script type="text/javascript" src="js/jquery-1.5.js"></script>
<script type="text/javascript">
var i=1;
$(document).ready(function(){
slideShow();
$("#next").click(function(){
slideShow();
});
});
function slideShow(){
if(i<3){
$("#slide-container").animate({ left:"+=35px" }, { duration:500})
$("#slide-container").animate({ left:"-=735px" }, { duration:250})
i++;
}
else {
$("#slide-container").animate({ left:"+=1400px" }, { duration:1000})
i=1;
}
setTimeout('slideShow()',2000);
}
</script>

Related

JQuery animation not running in correct sequence

I am creating a game called 'Pointless'. Pointless here is a game show in the UK. Anyway, there is a countdown which counts down from 100 to whatever score the team got. I am trying to replicate this. For an example, please see this video.
Anyway, I am trying to replicate the countdown myself, however whenever I try the whole thing gets executed at once instead of one div at a time like it should. I need to hide those divs one by one.
Please see this JSFiddle.
for (var i = 0; i <= 10 ; i++) {
$('#' + i).toggle('slide');
}
When you call toggle or any other animate functions in jQuery, it does not block the rest of the code. The animation continues on, while the rest of the code is running. You can add a delay for each of those blocks to start the animation.
You can try this one:
I also suggest you to use .slideToggle('slow') instead of .toggle('slide').
$('#' + i).delay(i*100).slideToggle('slow');
Because the .toggle() events (along with other events) are accually enqued and triggered after the execution of the entire for-loop. Or rather even if they where not, you are calling toggle on all of them nearly all at once, so they will all toggle at the same time. One way to get around it it to use a timer such as setInterval or setTimeout:
$('#Go').click(function(){
var i = 0;
var timer = setInterval(function(){
i++;
$('#' + i).toggle('slide');
if(i > 10) clearInterval(timer);
},100)
})
Fiddle Example
Amir solution is greate. I want juste to add a small correction :
toggle method of jQuery doesn't have any arguments whose value could be slide.
Here is the correct syntaxe :
$(selector).toggle(speed,easing,callback)
speed in [milliseconds, "slow", "fast"]
easing in ["swing", "linear"] (More easing functions are available in external plugins)
callback is a function

Simple jquery fader doesnt work in Chrome

I have built a really simple image fading gallery sorta thing, which works on firefox (and I'm sure worked on chrome before the holidays). However now Chrome just fades out the first image and never applies the .first class so subsequent animation is skipped.
JS
function doRotator(time){
$('.rotator3 .property.first').fadeOut(1500, function(){
$('.rotator3 .property.first').removeClass('first').next(".property").addClass('first').fadeIn(1500);
$(this).appendTo('.rotator3'); });
}
setInterval(function () { doRotator(3000);}, 3000);
JSFiddle: http://jsfiddle.net/pkyAS/1/
under each "property" div you have a div with "opacity:inherit" remove the "opacity:inherit" and it should work. let me know if there are more problems.
Here is my solution on fiddle.
I removed your interval, and made the "doRotator" run once - it was easier for me to debug
By the way - fadeIn(1500) is on your interval time.
If your interval is for 3000 millis, and you have fadeIn(1500) - then the div will be visible for 1.5 sec.
Consider triggering "setTimeout(doRotator,3000)" with 3000 when the fadeOut finishes.
EDIT : how to force removal of "opacity:inherit" - you can simply append some JS code to force that.
function doRotator(time){
$('.rotator3 .property.first').fadeOut(1500, function(){
$('.rotator3 .property.first').removeClass('first').next(".property")
.addClass('first').fadeIn(1500).find("div:first").css("opacity",null); $(this).appendTo('.rotator3'); });
}
setInterval(function () { doRotator(3000);}, 3000);

Simple slider with setInterval() with strange behavier

I'm trying to make simple slider by using setinterval and jquery.
you can have a look here http://jsfiddle.net/5m2Dq/
Slider works fine when it is in focus on browser but when we go to different tab for more than 5 min all the div's come's under each other, and start toggling.
$('#fbLoginSlide div:gt(0)').hide();
setInterval(function(){
$('#fbLoginSlide :eq(0)').fadeOut('slow').hide()
.next('div.loginSlide').fadeIn('slow')
.end().appendTo('#fbLoginSlide');
},2000);
Is there a simple way to achieve the sliding effect like this without any plugin.
This occurs probably because your browser starts missing timeouts. Especially if you are viewing another tab, the browser thinks that it is not important to call the callback with exactly 2 second intervals. You should ditch the setInterval function altogether! Use instead the completion callback of fadeOut and fadeIn to trigger the effects.
Try something like
var cycle = function() {
$('#fbLoginSlide :eq(0)').fadeOut('slow').hide()
.next('div.loginSlide').fadeIn('slow', function() { setTimeout(cycle, 1500); })
.end().appendTo('#fbLoginSlide');
};
cycle();

How to use javascript to monitor a change in a div value?

I have a page with a countdown in a DIV with id ="count"
I would like to monitor this div value so, when it reaches 0, a alert pops up.
I've gono so far as
if(parseInt(document.getElementById('count').innerHTML) < 2){}
But I don't know how to "listen" for the div changes
Can anyone help me?
Btw: it needs to be in pure javascript, with no such things as jquery.
Update:
I have no say so in the original code. It's an external page and I'm trying to run this code at the address bar
Presumably you have a function running based on setInterval or setTimeout. Have that function call your function when it gets to zero.
If you can't do that, you can try optimised polling - use setInterval to read the value, estimate when it might be near zero, check again and estimate when it might be zero, etc. When it is zero, do your thing.
There are DOM mutation events, but they are deprecated and were never well or widely supported anyway. Also, they are called when content changes so probably too often for your scenario anyway.
If you are changing the value of #count yourself then call the alert from that place. If not use:
window.setInterval(function(){
if(parseInt(document.getElementById('count').innerHTML) < 2) alert('Alarm!');
},1000); // 1s interval
UPDATE
To clear that interval:
var timer = window.setInterval(function(){
if(parseInt(document.getElementById('count').innerHTML) < 2) {
alert('Alarm!');
window.clearInterval(timer);
}
},1000); // 1s interval
//or by using non-anonymous function
function check(){
if(parseInt(document.getElementById('count').innerHTML) < 2) {
alert('Alarm!');
window.clearInterval(timer);
}
}
var timer = window.setInterval(check,1000);
The only efficient way to monitor this is to go to the code that is actually changing the div and modify it or hook it to call a function of yours whenever it updates the contents of the div. There is no universal notification mechanism for anytime the contents of div changes. You will have much more success looking into modifying the source of the change.
The only option I know of besides the source of the change would be using an interval timer to "poll" the contents of the div to notice when it has changed. But, this is enormously inefficient and will always have some of inherent delay in noticing the actual change. It's also bad for battery life (laptops or smartphones) as it runs continuously.
You don't listen for the div to change. The div is just there for a visual representation of the program's state.
Instead, inside whatever timing event is counting down the number, use a condition such as...
if (i < 2) {
// ...
}

A sticky situation for jQuery slideshow

I'm required to develop a slideshow (not an existing one) with jQuery. I was able to change picture with a function that I created named changePic (takes an image link). It incorporates the fading animation from the jQuery library.
For the slideshow I'm trying to use a while loop. It kind of works, except that it doesn't wait for the animation to finish.
How do I, a) wait for the animation to finish, b) delay the changing picture so it display the picture for a couple of seconds?
Also tried Settimeout, and it doesn't work.
Edit:
Basically changing image is like this:
function changePic(imglink){
var imgnode = document.getElementById("galleryimg");
$(imgnode).fadeTo(500, 0, function(){
$(imgnode).attr("src", imglink);
$(imgnode).fadeTo(1000, 1);
})
}
and the slideshow code is like this, but obviously it shouldn't.
function slideshow(gallerylinks){
var i=0;
while (i<gallerylinks.length){
changePic(gallerylinks[i]);
i++;
}
}
You could always try ditching the while loop, and going with a perpetually recursive function...
on the .animate, you could add a timeout function (at whatever interval) that calls the changePic function. As I have no idea what your code looks like, I will provide a fantastically generic outline.
/* array of imgUrls */
var imgUrls = new Array(); //populate it however
changePic(slideToShowIndex, fadeOutSpeed, fadeInSpeed, slideDelay)
{
$('#slideHolder').animate({ opacity: 0}, fadeOutSpeed , function(){
$('#slideHolder').attr('src', imgUrls[slideToShowIndex]);
$('#slideHolder').animate({ opacity: 1 }, fadeInSpeed, function() {
setTimeout(function() { changePic(slideToShowIndex+1, fadeOutSpeed, fadeInSpeed, slideDelay);}, slideDelay});
});
}});
}
$(document).ready(function() {
changePic(0, 5000, 5000, 10000);
});
This should (in theory) fade the image out, swap it with the new one, and fade it in (both taking 5 seconds) and then adding a delay to call itself with the next slide index in 10 seconds.
This is in no way perfect, but does outline the general idea. Since we have no idea what your code looks like, I can only assume your setTimeout was in the wrong spot. Doing it like this will make sure that the animation has finished before the timeout is set. This guarantees that the slide wont change until after the animation has changed.
of course you could always use a combination of the ':not(:animated)' selector and a setInterval to achieve much the same effect.
EDIT: made a slight change to stack the animations properly. The thoery behind this still works even with the OPs addition of code.
You could have provided more details or example code but have a look at stop() and delay() functions.

Categories

Resources