setTimeout goes mad after couple of minutes, FF6.0, Chrome 15
Take a look on my news roller: LIVE DEMO
Everything works perfectly till you leave scipt in the tab for couple of minutes.
What is happening looks like browser lost count of every 5s and is performing action constantly.
I'm guessing it has something to to with setTimeout
.
Any suggestion how to fix it?
Script:
(function($) {
$.fn.NoticeBoard = function() {
// Set a timeout
var timeOut = setTimeout(nextNotice, 5000);
// pause on hover
$('.noticeboard').hover(
function() {
clearTimeout(timeOut);
}, function() {
timeOut = setTimeout(nextNotice, 5000);
});
// Next notice function called on timeout or click
function nextNotice(event) {
clearTimeout(timeOut);
timeOut = setTimeout(nextNotice, 5000);
if ($('.noticeboard span:visible').is('.noticeboard span:last-child')) {
$('.noticeboard span:visible').fadeOut(300);
$('.noticeboard span:first-child').fadeIn();
}
else {
$('.noticeboard span:visible').fadeOut(300).next().fadeIn();
}
return false;
}
$('#notice-next').click(nextNotice);
$('#notice-prev').click(function(event) {
if ($('.noticeboard span:visible').is('.noticeboard span:first-child')) {
$('.noticeboard span:visible').fadeOut(300);
开发者_开发百科 $('.noticeboard span:last-child').fadeIn();
}
else {
$('.noticeboard span:visible').fadeOut(300).prev().fadeIn();
}
return false;
});
};
})(jQuery);
$(document).ready(function() {
$('.noticeboard span').hide();
$('.noticeboard span:first').show();
$('.noticeboard').NoticeBoard();
});
HTML:
<div class="action-box">
<!-- NOTICEBOARD NAV -->
<a href="#" id="notice-prev">«</a> <a href="#" id="notice-next">»</a>
<!-- /NOTICEBOARD NAV -->
<span class="ge"></span>
<div class="noticeboard" style="height: 145px;">
<span style="display: block; opacity: 0.515705;">
<strong>Boy, 14, found stabbed to death</strong>
<a href="http://www.bbc.co.uk/news/uk-england-14570107">A 14-year-old boy has been found stabbed to death in a park in north London.</a>
</span>
<span style="display: block;">
<strong>A-level passes rise for 29th year</strong>
<a href="http://www.bbc.co.uk/news/education-14558490">Hundreds of thousands of teenagers are getting their A-level results amid an intense battle for university places ahead of tuition fee rises.</a>
</span>
<span style="display: none;">
<strong>UK: Matter of time for Gaddafi</strong>
<a href="http://www.bbc.co.uk/news/uk-politics-14625484">Deputy Prime Minister Nick Clegg has said it is "only a matter of time" before Col Muammar Gaddafi is defeated.</a>
</span>
</div>
I think I've found your problem, don't really know how to solve it yet.
I think the issue you are facing is this: when you leave it open in a tab and then you hide the page by selecting another tab and then go back to your page after + 10 seconds(or minutes if you will) that the noticeboard keeps on flashing.
This is probably because jquery can't perform the visual effect when the tab is not currently selected. So it seems to me that it keeps all the effects in a queue and executes them one by one when you return to the tab. Don't know why it does that.
I've added a simple debug line to your nextNotice function to prove that the problem is not setTimeout
Simply add
var d = new Date();
$("#debug").append(d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() + " call to nextNotice<br />");
and add a div block somewhere with
<div id="debug"></div>
That will show you that the call is always made with a 5second delay.
Now to figure out why jquery is queuing the visual effects...
Also copy-pasting from the link in the first comment:
To avoid this potential problem, use the callback of your last animation in the loop, or append a function to the elements .queue() to set the timeout to start the next animation
So your code should change to this:
function nextNotice(event) {
if ($('.noticeboard span:visible').is('.noticeboard span:last-child')) {
$('.noticeboard span:visible').fadeOut(300);
$('.noticeboard span:first-child').fadeIn(300, function() {timeOut = setTimeout(nextNotice, 5000);});
} else {
$('.noticeboard span:visible').fadeOut(300).next().fadeIn(300, function() {timeOut = setTimeout(nextNotice, 5000);});
}
}
This will make sure that the new timeouts are only started when the animation finishes. So if you leave the tab, the last animation that hasn't played will not start a new timeout until you return to the tab.
Edit: Formatted code block properly
Edit 2: The first comment explains the reason for the problem I describe.
Edit 3: Added solution source code
setTimeout sets a timer that runs only once.
You might not need to clear it, once the timeout function hits, so try making this change
function nextNotice(event) {
// clearTimeout(timeOut);
And see how you get on. the clearTimeout in the hover is valid though.
Update:
I've moved the function around slightly, it appears to be working fine now, and setting the new timeout after the animation makes it feel a little smoother, he're my fiddle version:
http://jsfiddle.net/t4NXD/20/
精彩评论