A dose of animation can give your app that extra bit of pizzazz that it sometimes needs to impress the customer/ladies/gentlemen/whatever-floats-your-boat, so I thought it might be a good idea to quickly showcase some of Dojo’s animation facilities.
If you’re just now tuning in, you can click on my mugshot or this link to get to the first two posts of the ongoing “Dojo Goodness” series that I’m writing to promote my upcoming book, Dojo: The Definitive Guide, which is available on Amazon as well as the O’Reilly catalog.
One of the first things you should know is that some of the most commonly used animation functions are packaged right into Base while others that offer more frill are available via Core’s fx module. A way to help keep track of where everything is at is to look at the namespace–everything in Base is located in the base level dojo namespace, while the Core add-ons are available via the dojo.fx namespace. For this episode, we’ll be using the fadeIn and fadeOut functions as well as the uber-flexible animateProperty function that are all included with Base. We’ll tap into dojo.fx to get chain and combine, which can be used to chain together and combine animations, respectively.
You can use Dojo’s official API to get the full scoop on any of the specific functions mentioned, but for brevity, we’ll stick to the most basic usage here. For the fading functions, that amounts to a couple of one-liners to fade in and fade out a node. As the upcoming snippet suggests, Dojo’s animation API generally returns an object that you have to manually start via its play() method. In addition to getting some other finely grained control, this makes it that much simpler to chain and combine animations (as you’ll see in a moment.) Finally, some code:
//fade some nodes!
dojo.fadeOut({node : 'someNodeId'}).play();
//then sometime later...
dojo.fadeIn({node : 'someNodeId'}).play();
The animateProperty function is pretty intuitive as well and is used to animate arbitrary CSS properties. For the upcoming example, we’ll be using it to animate the height and width of a square on the screen to create an implode and explode effect like so:
//create an implode animation
var implode = dojo.animateProperty({
node : 'someNodeId',
properties : {
height : {end : 0},
width : {end : 0}
}
});
//create an explode animation (assumes width and height are both 0 when it is run)
var explode = dojo.animateProperty({
node : 'someNodeId',
properties : {
height : {end : 300}, //fill in whatever height/width you need...
width : {end : 300}
}
});
But wait–that’s not all. Simple animations are cool and all, but we can also spice it up by chaining and combining them; as you’re about to see, it’s as easy as it should be. Here’s the chaining portion, which entails nothing more than passing in a series of animation objects to the dojo.fx.chain function:
//chain together two fade animations
dojo.fx.chain([
dojo.fadeOut({node : 'someNodeId'}),
dojo.fadeIn({node : 'someNodeId'})
]).play();
Combining works the very same way. If you wanted to combine a fadeOut and the custom implode function, you could do it like so:
//combine two animations
dojo.fx.combine([
dojo.fadeOut({node : 'someNodeId'}),
implode //the same one we created a few moments ago
]).play();
That’s it for the animation part of this episode, but to give you a way to manage all of this mayhem, let’s use some Button dijits, which make it dirt simple to execute JavaScript code. In this particular example, we’ll use dojo/method SCRIPT tags to intercept the Button dijit’s onClick extension point and kick of an animation all from markup! The general pattern works thusly:
<div dojoType="dijit.form.Button">Do Something!
<script type="dojo/method" event="onClick" args="evt">
//you can inspect the W3C standardized event object, evt, or do something else like...
someAnimation.play();
//other sweet JavaScript code goes here...
</script>
</div>
So, without further ado, here’s the grand finale that puts all of this in perspective. This code creates a blue square in the center of your screen (relative to the viewport) and provides you with three buttons to control some animations. You should be able to copy and paste it directly into a local page and it should just work.
<html>
<head>
<title>Animation Station!</title>
<style type="text/css">
@import "http://o.aolcdn.com/dojo/1.0/dojo/resources/dojo.css";
@import "http://o.aolcdn.com/dojo/1.0/dijit/themes/tundra/tundra.css";
</style>
<script
type="text/javascript"
src="http://o.aolcdn.com/dojo/1.0/dojo/dojo.xd.js"
djConfig="parseOnLoad:true">
</script>
<script type="text/javascript">
dojo.require("dojo.fx"); //for dojo.fx.chain and dojo.fx.combine
dojo.require("dojo.parser");
dojo.require("dijit.form.Button");
dojo.addOnLoad(function() {
//get the dimensions of the current viewport
var viewport = dijit.getViewport();
var viewport_height = viewport.h;
var viewport_width = viewport.w;
//center a square in the viewport
var square_dimension = 300;
var e = document.createElement("div");
e.id = "square";
dojo.style(e, "width", square_dimension);
dojo.style(e, "height", square_dimension);
dojo.style(e, "background", "blue");
dojo.style(e, "position", "relative");
dojo.style(e, "left", (viewport_width-square_dimension)/2);
dojo.style(e, "top", (viewport_height-square_dimension)/2);
dojo.body().appendChild(e);
//chain together two fade animations
fadeAnim = dojo.fx.chain([
dojo.fadeOut({node : 'square'}),
dojo.fadeIn({node : 'square'})
]);
//set up an implode animation
var implode = dojo.animateProperty({node : 'square',
properties : {
height : {end : 0},
width : {end : 0}
}
});
//set up an explode animation
var explode = dojo.animateProperty({node : 'square',
properties : {
height : {end : square_dimension},
width : {end : square_dimension}
}
});
//chain together the implode/explode
implExplAnim = dojo.fx.chain([implode,explode]);
//combine the chained fades and the implode/explode
fadeImplExplAnim = dojo.fx.combine([fadeAnim, implExplAnim]);
});
</script>
</head>
<body class="tundra">
<div dojoType="dijit.form.Button">Fade In/Out
<script type="dojo/method" event="onClick" args="evt">
fadeAnim.play();
</script>
</div>
<div dojoType="dijit.form.Button">Implode/Explode
<script type="dojo/method" event="onClick" args="evt">
implExplAnim.play();
</script>
</div>
<div dojoType="dijit.form.Button">Both!
<script type="dojo/method" event="onClick" args="evt">
fadeImplExplAnim.play();
</script>
</div>
</body>
</html>
As a final note, the soon to be released Dojo version 1.1 (currently in Beta 3) contains a couple of enhancements that further simplifies some of the version 1.0 syntax and saves you some typing. If you’re browsing the online API, don’t let those enhancements catch you off guard since the code on this page is using the latest version 1.0.x bug fix release.
Until Dojo: The Definitive Guide comes out, be sure to check back here each week for more Dojo goodness.


Animations are nice, but sometimes you just want to hide or show an element, with no bells or whistles such as fades and whatnot. I've studied the tutorials, Dojo book online, and API docs for hours, and yet this one simple thing -- something built into competitors such as prototype -- I cannot find in dojo. This is where the project fails me -- the simple things are hard, which is not the way it should be. (Don't get me wrong -- I like dojo, and am using it for most of my ajax needs, but this part gets me every time.)
@Matthew: If I understand you correctly, then you'd perhaps want to just set a node's CSS "visibility" property to "hidden"? If that's all you want to do, then dojo.style(someNode, "visibility", "hidden") would do the trick. If that's not what you're looking to do, let me know. What you're trying to do *should* be a quick one-liner like that...
@ptwobrussel: basically, yes. But it's non-intuitive -- prototype has hide() and show() which are simple and tell you what they're doing. (Internally, hide() sets the display property to 'none', so in dojo you could do similarly, and indeed I've done so.) Dojo has great utilities and functionality -- don't get me wrong. The grids and charts are worth their weight in gold. But the simple things people do everyday -- autocompletion, hiding and showing nodes, etc. -- do not have simple, well-documented solutions. That's the one area where I'd like to see dojo improve.
@Matthew: Well, just so you know, we are *very* serious about improving documentation--hence, my upcoming book and the much improved API docs online to name two. The dojocampus.org site is also starting to see some really good growth. But as you hint, it won't all happen overnight, and your desire for better documentation is a very fair one.
One other important thing is to consider that somewhat differentiates Dojo is that it doesn't attempt to create an entire artificial layer on top of DHTML. Rather, it tries to plug holes where they need to be and leaves the rest as is. I can't say this authoritatively, but I would suspect that was the pragmatism used with not having something like a dojo.show and dojo.hide function i.e. the rationale might have been to leave it to dojo.style since we're essentially talking about CSS styling and dojo.style already does that quite effectively.
Anyway, just thought that backdrop might be useful. Thanks for taking the time to post something! I hope you'll keep reading
Now the trick is getting this to work in firefox...I tried and it worked in IE8 beta1, but not in firefox 2.0.0.14
oops! I take my last comment back, adblockplus was just blocking out the css sheet, my bad!
I am a beginner in Dojo. Thanks for this post. It is very informative. I have a question here. When I click on "Fade In/Out" or "Implode/explode" button, it works the first time. But after that, there is no change in the square. Also, if I click "Both!" button first, it works, but then the other two buttons would not work till I refresh the page. Can you throw some light on why this must be happening?
@Prajakta: The page seemed to work fine for me when I produced it on FF2, and AFAIK, it should work fine everywhere else too. What browser (and version) are you using that results in this behavior? Do you use Firebug? If so, do you notice anything unusual in the console?