AjaxPatterns
This is the original book draft version for the One-Second Mutation Ajax pattern, offered for historical purposes and as an anti-spam measure.
You're probably better off visiting the Live Wiki Version for One-Second Mutation instead, where you can make changes and see what others have written.

One-Second Mutation

Auto-Update, Sync, Synchronise, Sychronize, Real-Time

Goal Story

Doc monitors a patient's condition, watching some histograms shrink and grow to reflect any changes.

Problem

There's a lot of activity in an Ajax App - how can you help the user digest it all?

Forces

  • To ensure the user's working with current data, the browser display must be frequently updated.

  • With Ajax, it's possible to update only the portion of the screen that has changed; if nothing has changed, the display remains exactly as is.

  • The screen can get cluttered with a lot of information, much of which might be changing at any time.

  • While human vision is good at spotting changes, it's easy to miss a sudden change, especially if the change is a subtle one.

  • Even worse, there are different types of changes, and those differences are important to users.

Solution

When a page element undergoes a value change or some other significant event, dynamically mutate its shape for a second or so. In most cases, the mutation is used to reflect a permanent change. Instead of flipping from one form to another, the element gradually transitions into another form. The effect serves a couple of purposes:

  • The mutation and the extended transition time make it likely the user will notice that something's happened.

  • The type of mutation will hint at what sort of action has taken place.

  • The gradual shift in appearance will feel more natural than an instant transformation.

Mutation combines “Display Morphing” with “Scheduling”. A loop runs while the second of mutation progresses, with each transition occurring perhaps once every 50 milliseconds. Each transition will likely involve a change to at least one of the following CSS properties:

  • width - An object can be thinned or fattened with its width value.

  • height - An object can be heightened or shortened with its height property.

  • backgroundImage - Instead of just resizing the element, it's possible to swap in a completely different image. Just like a movie, the DOM element quickly flips through various images to give the illusion of mutation. See the DHTML Lemmings walkthough in “Sprite” for more details.

  • position - Manipulating position with position, left, right, top, and bottom is possible for certain mutation effects.

  • overflow - Overflow can be set to hidden to enable the entire element to be present on the page, but only show a certain portion of it.

The first category of mutation involves making an object appear. These can be effective ways to communicate the object has just been created or retrieved from the server.

  • Form - An item "forms" from nothing to its standard appearance, typically by incremental, outward, growth. It might grow from the centre of the object, or a corner, or some other position entirely. Typically, width and height increase at the same time.

  • Slide Out - An item slides out. If the item slides in from the side, it appears to be pushed out like a sliding door. If the item comes in from the top, it appears like a garage door being unrolled. If coming in from the bottom, the item appears to rise from the ground. Usually either width or height is fixed, while the other dimension gradually increases, all while the position also changes.

  • Reveal - An item is gradually revealed. It appears that the item has been there all along, and a cover is gradually being lifted off. Here, one or both of width and height incrementally increases, while overflow is set to hidden so that part of the element is covered.

This next category of mutation involves some common disappearing acts - the opposite of the effects above - and a special effect for disappearing:

  • Disappear - An item changes from its standard appearance to nothing.

  • Slide In - An item slides in from the top, side, or bottom.

  • Cover Up - An item is gradually covered up in one or both dimensions.

  • Blow Up - An item expands outward from its current side and simultaneously fades out to nothingness.

There are also a few mutations that involve changing from one thing to another:

  • Grow - An item grows from one size to another. Height or width (or both) increases.

  • Shrink - An item shrinks from one size to another. Height or width (or both) decreases.

  • Metamorphise - An item shifts from one appearance to another. This is typically achieved with a change in background image. See “Sprite” for more details.

Most of these effects can be combined with “One-Second Spotlight” to give a 3D effect. For example, an item can Materialise and Form at the same time. The human visual system uses both ambience and size as cues for distance, so the effect is that the item is reaching outward from behind the screen and towards the user.

Note that you probably won't have to hand-code effects, because libraries like scriptaculous (discussed in Real-World Examples below) are quite flexible, and usually easy to incorporate into typical scripts.

Decisions

Most of the decisions in “One-Second Spotlight” are relevant here too. As with “One-Second Spotlight”, the "One-Second" name is only a guideline.

Real-World Examples

TiddlyWiki

Jeremy Ruston's Tiddlywiki, like many of its spinoffs, uses a Grow effect to introduce some new content when you click on a “Microlink”. The “Microlink” itself is the starting point, and the new content block appears to leap out and, as it flows outward, grows into a full “Malleable Content” block (Figure 1.83, “Tiddlywiki Motion-Mutation Sequence”). Actually, there are a few visual effects at work here:

There are a few variations possible, depending on whether the content is already open and where it's placed.

Figure 1.83. Tiddlywiki Motion-Mutation Sequence

Tiddlywiki Motion-Mutation Sequence

Scriptaculous Library

As mentioned in “One-Second Spotlight”, scriptaculous is a general-purpose Javascript library. Its visual effects demo provides many of the mutation effects described here.

DHTML Lemmings

DHTML Lemmings is a full-featured implementation of the Lemmings PC game, which uses DOM manipulation to show the lemming creatures performing typical lemming-like activities, such as walking, digging, and clutching an umbrella to make a safe descent from the top of a cliff. As the characters move along, their appearance is animated using quick mutations. While the usage is somewhat different from the usual type of mutation which tends to focus on highlighting particular pieces of information, it is still of particular interest because it involves manipulation of images instead of just CSS style. See the code walkthrough in “Sprite” for more details.

Code Example [TiddlyWiki]

Let's look at how TiddlyWiki shows the Grow effect discussed above. In doing so, we'll see how its generic animation engine works.

TiddlyWiki delegates animation to an Animator, which is capable of animating according to a list of Strategy (Gamma et al., 1995) objects, animations. Each encapsulates the strategy for a particular animation. At this time, there are just a couple of animation objects: a Zoomer and a Slider.

    var anim = new Animator();

    function Animator()
    {
      ...
      this.animations = []; // List of animations in progress
      return this;
    }

When a “Microlink” is clicked, the Animator is passed a Zoomer strategy, which is injected with the Microlink DOM object from which the content will leap out (src), a string title of the “Malleable Content” (title), the “Malleable Content” element where the content will end up (theTiddler), and an a flag indicating if the animation should be slow or not (I assume this is for debugging, and you can activate it by holding down shift or alt as you click on the link):

    anim.startAnimating(new Zoomer(title,src,theTiddler,slowly));

startAnimating() pushes the new animation onto the list of running animations. If not already running, it sets up an animation loop:

    Animator.prototype.startAnimating = function(animation)
    {
      this.animations.push(animation);
      if(this.running++ == 0)
        {
        var me = this;
        this.timerID = window.setInterval(function() {me.doAnimate(me);},25);
        }
    }

The loop runs every 25 milliseconds. It calls a tick() function on each running animation. By analysing Zoomer's tick(), you can see how the One-Second Mutation is achieved. On construction, Zoomer has already set up a bunch of variables to support this function, as well as an element (element) to be shown during the transition. The variables hold position information about the start and end elements. tick(), then, is left with the task of interpolation: "if the item starts at point A and ends at point B , how should it look at a particular point in the journey?" The Animator provides a value (f between 0 and 1 to define how far along the animation the object is, which makes things much easier. So, if the value is 0.5, the item's width will be halfway between the original width and the item's final width (Figure 1.84, “Growth Factor”). The same idea applies for height and position:

Figure 1.84. Growth Factor

Growth Factor
    this.element.style.left =
      this.startLeft + (this.targetLeft-this.startLeft) * f + "px";
    this.element.style.top =
      this.startTop + (this.targetTop-this.startTop) * f + "px";
    this.element.style.width =
      this.startWidth + (this.targetWidth-this.startWidth) * f + "px";
    this.element.style.height =
      this.startHeight + (this.targetHeight-this.startHeight) * f + "px";

A “One-Second Spotlight” effect is also used here, as the target object - the place where the object is "leaping" towards - gradually fades in, using the opacity property (and filter, for compatibiity). Finally, the window is scrolled to show the target object:

    this.targetElement.style.opacity = this.progress;
    this.targetElement.style.filter = "alpha(opacity:" + this.progress * 100 + ")";
    window.scrollTo(0,this.startScroll + (this.targetScroll-this.startScroll) * f);

The purpose of mutations is generally to provide a smooth transition from one state to another. Therefore, the final state should generally be reached simply by running the animation for the right period. No special handling needs to take place at the end, right? Well, in practice, there are rounding errors and approximations which make it good practice to explicitly set the final state. Thus, the Zoomer completes the animation by ensuring the precise opacity is precisely 1 (in fact, the filter should ideally be set here too, as a further security against rounding errors). The function also deletes the transient element it had created to leap from source to target:

    Zoomer.prototype.stop = function()
    {
      this.element.parentNode.removeChild(this.element);
      this.targetElement.style.opacity = 1;
      window.scrollTo(0,this.targetScroll);
    }

Alternatives

“One-Second Spotlight” and “One-Second Motion” are also used to draw attention to a significant event. One-Second Mutation is particularly suited to indicating certain types of changes have occurred, such as object creation and removal, as opposed to general-purpose attention-grabbing.

Related Patterns

“Sprite”s are often changed in rapid succession to give the impression of a smooth transition.

Metaphor

Many of the individual effects have their own metaphors - that's why they're used! Slide Out looks like a physical object sliding outwards, Grow looks like an object growing outward, and so on.

Acknowledgements

Many of the effects discussed in the Solution are based on an analysis of the Scriptaculous implementation. Jeremy Ruston's TiddlyWiki code was also instructive, and Jeremy helped clarify part of the code.

Live Wiki Version for One-Second Mutation