Reputation: 399
What I am trying to do is to clear the html on a page, insert a single div, give it a backgound image, fade it in, keep it there for a few seconds, fade it out and then return to the previous html. I'm doing this:
var body_html = $('body').html();
$('body').queue(function(){
$(this).empty().css('background-image','none').html('<div class="start-img"></div>');
$(this).dequeue();
}).queue(function(){
$('.start-img').html('<img src="'+url+'public/img/holding.jpg">').fadeIn(1000).delay(10000).fadeOut(500);
$('.start-img').dequeue();
}).queue(function(){
$(this).html(body_html).css('background-image','url("../img/paper-bg.jpg")');
$(this).dequeue();
});
I have spent a ridiculous amount of time googling but this seems to match the examples I've seen and it doesn't work. Firebug shows no errors. What happens is the page goes blank and the background image (holding.jpg) fades in for about one second, then fades to a blank page. When I view the generated source, only the div.start-img is present as html.
I've never used queue() before and I must have misunderstood it but can anyone set me right? Even if there is a better way of doing it, why does my code not work?
Upvotes: 0
Views: 1318
Reputation: 7148
I'm not an expert with jQuery's queue method. (I've never used it before.) But I think I spot a couple problems here:
1. Dequeue events must be paired with same targets as the initiating queue event
So in step 2, the line:
$('.start-img').dequeue();
Should be:
$(this).dequeue();
2. You're treating asynchronous events as if they were synchronous
Again in step 2: you have a fadeIn
effect chained to a long delay chained to a fadeOut
effect. This is going to take some time to complete. But the next line, the dequeue
call, is going to execute immediately, which I expect will immediately move the queue to the next step and wreck havoc on your sequence.
Solution
Wait until any asynchronous events have completed before making the dequeue
call to move on to the next queue event.
Here's a fiddle that demonstrates a sequence of steps like that which you describe in your question: http://jsfiddle.net/klenwell/wg4jqdjs/
Here's the queue code:
var $newDiv = $('<div />').html('<h4>new block</h4>').hide();
$body
.queue(function() {
$body.children().fadeOut(1000, function(){ $body.dequeue(); });
})
.queue(function() {
$body.append($newDiv);
$newDiv.fadeIn(1000, function(){ $body.dequeue(); });
})
.queue(function() {
$newDiv.animate({backgroundColor: "red"}, 1500, function(){ $body.dequeue(); });
})
.queue(function() {
setTimeout(function(){ $body.dequeue(); }, 2000);
})
.queue(function() {
$newDiv.fadeOut(1000, function(){ $body.dequeue(); });
})
.queue(function() {
$body.find('h4:eq(0)').fadeIn(1000, function(){ $body.dequeue(); });
});
Notice how the dequeue
calls are made in the on-completion callbacks of the various asynchronous events.
Addendum
It would have been a little cleaner to have just passed the dequeue
call to the various effect callbacks, like this:
$body.children().fadeOut(1000, $body.dequeue);
But, unfortunately, that was raising an error in my fiddle.
Upvotes: 2