Internet Performance Delivered right to your inbox

Why jQuery.queue Should Be Your New Best Friend

As the web matures and evolves, I find that more and more websites are embracing JavaScript libraries to do their dirty work. Whether it be an AJAX call or a simple slide animation, building those calls from scratch is not a quick task. Why continue to reinvent the wheel when so many people have already done it and are willing to give it away for free?

But with so many wheels out there, you are best picking one to roll with to avoid compatibility issues. It’s no secret that my favorite JavaScript library is jQuery and it’s no coincidence that it’s the library of choice with our SmartMTA email delivery application.

For me, jQuery goes above and beyond to integrate smoothly with any web application, saving hours of time. When you can save time without sacrificing quality, it’s definitely a win-win.

Get into the .queue

jQuery has tons of features to use and choose from, and that’s before you dive into the plugin world. One of these features is jQuery.queue. jQuery.queue hasn’t been around too long and was added in 1.3 and abruptly overshadowed by live(), which also made its debut in the same version. jQuery.queue does exactly what you’d think it would do, allowing you to modify or read a queue such as the animation or event queue. Queue has a sibling as well named dequeue, which removes items from a queue.

Like many of the functions on the jQuery API site, the jQuery.queue documentation feels incomplete or is at least written in such a way that it doesn’t adequately show you its best potential use. I’m well aware the authors of those articles devoted hours writing that documentation and probably spent even more time revising them, but some of them don’t seem up to par with how awesome the function is or can be.

jQuery.queue can be used in two ways. The first “shows the queue of functions to be executed on the matched elements.” To be honest, I haven’t quite run into a moment where this would be efficient or even useful for me to use. The second, however, does a lot more than it seems to let on. From the way it reads, at least to me, jQuery.queue allows you to add effects functions to a queue so they run in a sequence, much like stringing them together already does. This is merely the smooth surface of what lays deep below. With jQuery.queue you can also run arithmetic, animate additional objects, add/remove classes, etc.

The Downlow

Before I explain how to use it, I should mention that the default queue name “fx” references the effects (“animation”) queue functions. You can find a list of them here.

So here’s how one would apply effects to an object, the “old” way:

$(‘#someDiv’).fadeOut().fadeIn();

You’ve seen this, you know it. I’m sure I don’t have to explain it. To achieve the same outcome using the queue, you would do this:

$(‘#someDiv’).fadeOut().queue(function(){
	$(this).fadeIn();
	$(this).dequeue();
});

Notice how “fadeIn” is added to the default “fx” effects queue via a wrapper function, then removed from the queue. Oh, if you forget to dequeue every item you queue, your animation will happen only once.

Now this is admittedly an over-simplistic (and counterproductive) example since I added more steps to something that didn’t need it. Let’s look at a more useful application of jQuery.queue.

…
function(){
	var $m = $(this).find('ul');
	$m.css({left:'1000px'}).show().delay(1).queue(function(){
		var $p = $m.parents('li:first');
		var h2 = $m.height();
		var h = $('.BodyContainer').height();
		if($p.position().top > (h - h2))
			$m.css({top:'-'+(h2+18)+'px'});
		$m.css({left:'-10px'});
		$(this).dequeue();
	});
},
…

This is a small chunk of code from the EMS version of SendLabs that we released in late-2010 as part of a big UI update. This chunk of code determines where a hover menu will sit, based on its location. If we reach the bottom of the screen, we don’t want the menu extending past it and instead want it to display higher so it appears in full on-screen.

Now in Internet Explorer, you can’t calculate the height of a hidden element, so to get the height of the element you need to first show the element. Originally I had attempted to show the menu ($m) and then tried to calculate the height. This didn’t work because the show command isn’t instant. The menu still requires some time to render itself to the DOM so I was still getting a calculated height of 0.

At this point, I was pretty upset and decided that I’d just throw in a delay of 1 millisecond before I tried to figure out what the height was. Here’s where jQuery.queue came in to save the day. Normally if I wanted to wait a specific amount of time, I’d use setInterval, create a new function and figure out a way to pass certain values to it. With jQuery.queue I don’t even have to break user flow. Following the delay of 1 millisecond, you will see a call to queue() and a function inside.

Everything inside that function won’t start until the delay has completed because I added it to the existing (default) queue. (Note: The addition of that css ({left:’1000px’}) was used to avoid the ugly chop this was creating since I was waiting a millisecond before I did anything to the menu. You’ll see I moved the element back at the end of the queued function.)

There’s one more use for jQuery.queue. I shouldn’t even be talking about it as the Firefox fanbase will most likely clobber me for bringing it up. JavaScript animation isn’t always smooth in Firefox (the browser I love so dearly), which can create some pretty bad user experiences if your site likes to use things like the slide animation to pretty itself up. There are a number of reasons why your animation could turn out choppy and I can’t pretend I know all of the reasons why and how.

One reason it “could” happen is if you are trying to do too many things at once, or modify the same element while you’re animating it. A solution to this is to group all of your functions that supposedly happen before your animation and throw them all in a queue so they are sure to complete before the animation gets called. This will ensure that the animation is run by itself, and not with any of the calculations that proceed it.

An example of that would look like:

var dist = 0;
$(‘#someDiv’).queue(function(){
	$(this).css({color:’#F60’);
	$(this).dequeue();
}).slideDown().queue(function(){
	dist = Math.sqrt(1764);
	$(this).dequeue();
}).animate({left: dist }, 1000);

Why you would do what’s above is beyond me but every function above will occur in sequential order. So by the time it gets to move the div to the left “dist” pixels, all previous calculations and other animations are already done.

I hope this helps you understand the usefulness that is the jQuery queue. Good luck in your jQuery adventure and see you at the conference this weekend!


Share Now

Whois: John Norton

John Norton is a Senior Software Engineer at Oracle Dyn Global Business Unit, a pioneer in managed DNS and a leader in cloud-based infrastructure that connects users with digital content and experiences across a global internet.