Chaining Functions in Mootools for Dynamic Text Effects
February 28th, 2009 | Published in Chaining, Demo, Javascript, Mootools, Text Effects | 10 Comments
First, click HERE so you can see what I’ll be referring to below.
Dynamic text effects (fade ins, moving text, etc.) can enhance the viewer experience by directing attention to specific (and presumably important) areas of the page. All well and good. But how do you do this?
Some of the things I like about Mootools are its class-oriented approach, its outstanding plugins and the ease with which you can put together complex effects. But we won’t be creating a class here. We’re going to keep this real simple…
I recently needed to animate some text on a page: specifically, I had to fade in several (distinct) elements in the page header, and produce a fade-in/fly-in effect for some text in the main content area. By itself, this wasn’t hard to do but the kicker was that the effect for each element had to fire off in sequence, one after the other. It had to go Snap, Crackle, Pop! What I didn’t want was for the effects to fire together because then I’d end up with a snapplepopackle mess.
So I turned to the Mootools Chain class for assistance. Let’s look at the code behind the demo page; it’s short and to the point. Relatively speaking, that is.
window.addEvent('domready', function(){
var fnChain = new Chain();
var hdrItems = $$('.sub-header-item');
var sayings = $$('.saying');
hdrItems.each(function(item) {
item.setStyle('opacity', 0);
item.set('morph', {
duration: 1200,
onComplete: function(){fnChain.callChain()}
});
fnChain.chain(
function(){item.morph({
opacity: 1,
backgroundColor: '#fff',
borderColor: '#fff',
color: '#002a46'});
}
);
});
sayings.each(function(saying) {
saying.setStyle('opacity', 0);
saying.set('morph', {
duration: 800,
transition: Fx.Transitions.Bounce.easeOut,
onComplete: function(){fnChain.callChain()}
});
});
fnChain.chain(
function(){$('where').morph({opacity: 1, left: 180});},
function(){$('when').morph({opacity: 1, right: 185});},
function(){$('final').morph({opacity: 1});}
);
(function(){fnChain.callChain();}).delay(1000);
});
Let’s start at the top and work our way down. Within the ‘domready’ event handler code, we first create an instance of the Mootools Chain class and stick a reference to it in fnChain. Then we create a couple of local variables to hold references to the elements we want to apply the effects to.
Next we iterate over the elements containing the header text in the hdrItems array and do several things: first we set the opacity to 0 so that they’re invisible when the page loads; second, we create default instances of Fx.Morph for each element in the array (we’ll come back to this in a second); third, we take our default Fx.Morph instances, apply the morph method to generate a transition and load this onto the fnChain call stack.
Here’s the important thing about getting the Mootools Chain class to do what you want: using the chain and callChain methods is analogous to loading and firing a gun. The analogy works like this: calling the chain method simply loads the gun with bullets, whereas invoking callChain fires a single bullet. Okay, that isn’t too hard to grasp … wait, there’s something missing. Ah, the finger that pulls the trigger! We kind of need that, don’t we?
That’s where the onComplete event of our Fx.Morph instances comes in: it’s the finger that pulls the trigger. And it only pulls the trigger when the last effect has finished. Setting it up this way ensures that all functions loaded onto the fnChain call stack get used. Using the chain and callChain methods by themselves will not get us where we want to be.
The last sections of code (with the exception of the last line) basically repeat the process for the text in the content area. The final line:
(function(){fnChain.callChain();}).delay(1000);
is needed to get that first function from the call stack and kick the process off.
If you’re into Mootools I hope you’ll add the Chain class to your toolkit. With it, you can kick up the complexity of your effects by a notch or two. Thanks for reading.
March 1st, 2009 at 9:23 am (#)
Very well explained. The analogy really helps communicate how it works very well!
March 1st, 2009 at 1:29 pm (#)
Thanks, Ryan. Regarding the analogy, I thought about adding a disclaimer saying I wasn’t advocating the indiscriminate use of firearms. Then I thought, “Naw, that’s way too PC!”
March 2nd, 2009 at 9:27 am (#)
You should try Fx.Elements with the option ‘link’ set to ‘chain’, it’s a even easier. The only downside is that you have to know how many elements you are dealing with and the position of each in the collection, while your method is more abstract
March 2nd, 2009 at 9:46 pm (#)
olivier, I agree with your comment about Fx.Elements. It is easier (and more elegant).
May 8th, 2009 at 12:08 pm (#)
You have saved my life with the function above!! Many many THX!!!
May 9th, 2009 at 5:32 pm (#)
Wow, you’re welcome. Made my day!
May 11th, 2009 at 8:22 am (#)
Hi,
i like it is efect.
Thank you
June 25th, 2009 at 1:23 pm (#)
Also important is the CSS: giving elements “position: absolute;” is what allows setting left, top, etc.
h2.saying {
position: absolute;
top: 40px;
}
h2#where { left: 0; }
h2#when { right: 0; }
h2#final { left: 272px; top: 80px; }
July 30th, 2009 at 11:08 am (#)
Hi there!
Kudos to you for that beautiful snippet.
Finally I understood chaining, thank you very much!
Kind regards,
mtness
December 2nd, 2009 at 2:15 pm (#)
lol “way to PC” what a MAC zellot… lol
Thanks for tut anyway