Thomas Fuchs
Hi, I'm Thomas Fuchs. I'm the author of Zepto.js, of script.aculo.us, and I'm a Ruby on Rails core alumnus. With Amy Hoy I'm building cheerful software, like Freckle Time Tracking and Every Time Zone and write books like Retinafy.me.
   Want me to speak at your conference? Contact me!

script.aculo.us morph effects

November 21st, 2006

script.aculo.us 1.7 beta 1 is out now (see below!)—and the big new thing is Effect.Morph which allows for CSS style-based effects, and its companion, the Effect.Transform shortcut to set up complex animations in a snap (while I’ve been thinking of adding this for some time now, there’s some inspiration coming from Bernie’s Better Animation Class).

Look at the demos first, then return here to get the nitty-gritty details!

Let’s look at how Effect.Morph is used:

1
2
3
new Effect.Morph('error_message',{
  style:'border-width:3px; font-size:15pt; color:#f00'
});

This will start an effect to morph the div element with id error_message smoothly from whatever border-width currently is set, whatever font-size is set (note the currently set font-size must have the same unit, in this case pt), and whatever color is set to the given new values. Because Effect.Morph queries the original values with Prototype’s Element.getStyle API, it doesn’t matter whether these styles are set inline or in an external stylesheet definition. Of course the effect supports all usual options, like duration or transition.

It internally uses a new addition to the String API in script.aculo.us 1.7, that is String.prototype.parseStyle. This method is smart about how to parse CSS style properties correctly. For example, it will automatically parse a ‘border-width’ property to be split up in ‘border-left-width’, ‘border-top-width’ and so on. This allows you to use styles freely as you do in everyday CSS files.

But! Prototype and script.aculo.us are about making development easier, having less stuff to type and think about, and handle common cases with the utmost niceness:


$('error_message').morph('font-size:15pt; color:#f00');

.morph() ia automatically available for all elements. It takes an optional second argument, an object that’s given to the generated Effect.Morph. You can use this to chain morph effects, like this:


$('blah').morph('background:#800').morph('background:#fff',{delay:3});

Effect.Transform is a helper that doesn’t generate a normal effect, but stores a more complex set of Effect.Morph effects to be generated when called upon.

Let’s see an example of how this works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// define the Effect.Transform and store for later
var transformation = new Effect.Transform([
  { 'div.morphing': // divs with CSS class 'morphing'
      'font-size:20px;padding-left:40em;opacity:0.5' },
  { 'error_message': // or '#error_message'
      'width:480px;border-width:10px;' + 
      'border-right-width:20px;' +
      'margin:20px;margin-bottom:-20px;' +
      'font-size:30px;' +
      'background:#954' }
],{ duration: 1.3 });

// sometime later
transformation.play();

Effect.Transform takes an array of tracks, which are defined in a ‘identifier or CSS selector’: ‘style’ syntax, and generates Effect.Morph effects when you call the play() method. You can also add additional tracks later on, which the addTracks() method.

Notably, you can use DOM object ids or CSS selectors to choose which elements should be acted upon—which means that at any given time you call play(), Effect.Transform will automatically choose the correct elements for the effects, given on these rules. Also, you can an Effect.Transform when none of the referenced elements are already rendered—as long as they are there when you actually call play().

If you need a complex one-shot effect, you can also do this:

1
2
3
4
5
6
7
8
9
// one-shot transformation
// shrink and fade info messages, 
// highlight error messages
new Effect.Transform([
  { '#messages li.info':
      'font-size:1px;height:0px;opacity:0' },
  { '#messages li.error':
      'font-size:12px;background:#fee;color:#f00' }
],{ duration: 1.3 }).play();

The 1.7 beta version also contains the newest Prototype 1.5.0_rc2 library, fresh from SVN, which fixes lots of things here and there.

With your help (beta testing gives good karma!) we can hopefully sort any bugs out and have this released soon (maybe as an Xmas present?)!

So, get started by downloading from SVN, or use this link to get 1.7.0 beta 1. If you use Ruby on Rails, be sure to grab edge Rails, or the 1-2-prerelease branch, which both include the beta.