Section 4.1. Visual Effects


4.1. Visual Effects

The most popular component of script.aculo.us is its Effect object, which is used to attach a variety of cinematic effects to UI events. Using script.aculo.us effects, many of the slick animated transitions that people have come to associate with Flash can be accomplished without plug-ins at all, and in a way that preserves the benefits of HTML.

What about cross-platform compatibility? In general, the script.aculo.us visual effects work reliably across different browsers (Internet Explorer 6+ for Windows, Firefox, Safari, Konqeror, Camino, and, with a few exceptions, Opera). And because the animated effects are time-based (as opposed to frame-based) they work consistently on systems of different speeds. You might be wondering: just because visual effects are easy, does that mean they're a good idea? Isn't it just eye candy? And what does it have to do with Ajax, anyway?

The full answer to those questions will come in Chapter 6, but here's the short one. More than just mere decoration, visual effects can be essential to providing a good user experience, especially in conjunction with Ajax. For more than 10 years, users have gotten used to the way the Web works, and Ajax undermines many of their expectations. For example, there's a basic expectation that web pages are static, that they won't change once they're loaded. But in the last chapter, all the Ajax examples made changes to the page without reloading, which has the potential to become confusing. To address that, visual effects can provide cues that make the interface more natural and discoverable.

A word of caution: just like special effects in the movies, script.aculo.us effects are generally best when you don't notice themwhen they are subtle and unobtrusive, they and contribute something to the plot. Remember when desktop publishing arrived in the 1980s, and every neighborhood newsletter suddenly used 10 different fonts, because it could? If at all possible, try not to get similarly drunk on the power of script.aculo.us.


The script.aculo.us' Effect object is where the magic resides. Let's look at it. First, we'll need an element to try our effects on, so add one to the top of the new index.rhtml:

<div  >   <div>Here's a DIV with some text.</div> </div>

Now let's use the link_to_function to call an effect on the new element. Add this below the DIV:

<%= link_to_function "Fade", "new Effect.Fade('target')" %>

Remember, link_to_function takes two arguments: the first is the text for the link, and the second is a JavaScript statement to be evaluated. In this example, that statement is a method call on script.aculo.us' Effect.Fade. Load the page in your browser and try out the linkyou should see the target element slowly fade away, until it's removed from the page flow altogether. Internally, the first argument to Fade( ) is passed through Prototype's $( ) functionwhich means you can pass it either the ID of an element or an element reference itself.

There's another way to trigger effects, thanks to the fact that Prototype's Element methods are added to every element that is accessed via $( ). That means you can call visualEffect directly on a DOM element:

$('target').visualEffect('fade')

script.aculo.us has five core effects that control fundamental aspects of an element: Opacity, Scale, Move, Highlight, and Parallel. To get a feel for each:

<%= link_to_function "Opacity",     "new Effect.Opacity('target', {to:0.5})" %> <%= link_to_function "Scale",     "new Effect.Scale('target', 200)" %> <%= link_to_function "Move",     "new Effect.Move('target', {x:50,y:10})" %> <%= link_to_function "Highlight",     "new Effect.Highlight('target')" %> <%= link_to_function "Parallel",     "new Effect.Parallel([       new Effect.Move('target', {x:50,y:10}),       new Effect.Opacity('target', {to:0.5})      ])" %>

In your application, you'll usually use combination effects, which are composed of the core effectsoften by means of Effect.Parallel. script.aculo.us includes 16 standard combination effects, but you can define as many new ones as you like. Here are the standard ones:

Fade  Appear

Gradually decreases or increases an element's opacity. Once a fade is finished, the element's display property is set to none, so the rest of the page will reflow as if it's not there.
BlindUp BlindDown

Works like Venetian blinds: gradually changes the height of the element, leaving the contents of the element fixed in place.
SlideUp SlideDown

Similar to BlindUp and BlindDown, except that the contents of the element appear to slide up and down with the element. Note that unlike the other combination effects, the slide effects require a wrapper DIV surrounding the content inside of the target DIV.
Shrink Grow

Resizes the entire element, including its contents, from the center point.
Highlight

Changes the background color of the element (to a pale yellow by default), and then gradually returns to the previous color. Commonly used when you need to draw the user's attention to part of a page.
Shake

Causes an element to slide left to right a few times, commonly used to indicate that an element is invalid.
Pulsate

Rapidly fades an element in and out several timesa modern twist on the much-beloved <blink> tag.
DropOut

Simultaneously fades an element and moves it downward, so it appears to drop off the page.
SwitchOff

Simulates an old television being turned off: a quick flicker, and then the element collapses into a horizontal line.
Puff

Makes an element increase in size while decreasing in opacityso that it appears to dissolve into a cloud.
Squish

Similar to Shrink, but the element's top-left corner remains fixed.
Fold

First reduces the element's height to a thin line and then reduces its width until it disappears.


To try out all the standard combination effects, you could write a link for each one. Instead, let's keep things DRY by iterating through an array instead:

<% %w( Fade Appear Highlight Fold Pulsate SlideUp SlideDown         Shrink Grow Squish Shake DropOut SwitchOff Puff BlindUp         BlindDown ).each do |name| %>   <%= link_to_function name, "new Effect.#{name}('target')" %> <% end %>

4.1.1. Toggling

Some of the effects are grouped into pairs (Fade/Appear, BlindUp/BlindDown, and SlideUp/SlideDown). script.aculo.us provides a convenient method to toggle between the effects, Effect.toggle:

Effect.toggle('target') /* uses Fade/Appear */ Effect.toggle('target', 'blind') Effect.toggle('target', 'slide')

4.1.2. Options

The Effect.* methods take an optional second parameter: a hash of options. Some options are effect-specific, but we'll look at those that apply to every effect.

duration specifies how long the effect should last, in seconds. For example:

<%= link_to_function "Fade",       "new Effect.Fade('target', { duration:5 })" %>

fps determines the frames per second. The default is 25, and it can't exceed 100. For example:

<%= link_to_function "Choppy Fade",       "new Effect.Fade('target', { duration:10, fps:2 })" %>

Note that because script.aculo.us effects are time-based, rather than frame-based, slower systems will automatically drop frames as necessary.

delay specifies the time in seconds before the effect will be started. For example:

<%= link_to_function "Fade",       "new Effect.Fade('target', { delay:2 })" %>

from and to define the starting and ending points of the effect as values between 0 and 1. For example, you could jump directly to the halfway point of an effect, then gradually fade to 25 percent, and then stop:

<%= link_to_function "Fade with from",       "new Effect.Fade('target', { from:0.5, to:0.25 })" %>

4.1.3. Queues

In some circumstances, you may want to chain effects, so that they occur sequentially. As a first attempt, you might simply call one effect after the other:

<%= link_to_function "Blind Up/Down",       "new Effect.BlindUp('target');        new Effect.BlindDown('target')" %>

Unfortunately, this won't have the desired result. As new effects are created, script.aculo.us adds them to a global queue. By default, these effects are executed in parallelwhich means these two effects will collide with each other. To specify an effect's position in the queue, use the queue option:

<%= link_to_function "Blind Up/Down",       "new Effect.BlindUp('target');        new Effect.BlindDown('target', { queue: 'end' })" %>

Now the two effects will execute sequentially, rather than at once. If you want more than two effects sequentially, just keep adding them with a queue of end. The queue option can also take a value of front, which causes the effect to be executed before anything else in the queue.

script.aculo.us also supports multiple queues, so that you can create named scopes for effects queues that run independently. For more information on creating queue scopes, see Chapter 11.

4.1.4. Callbacks

The options hash can also take parameters for callbacks that are executed through the effect's life cycle. beforeStart is called before the main effects rendering loop is started. beforeUpdate is called on each iteration of the effects rendering loop, before the redraw takes places. afterUpdate is called on each iteration of the effects rendering loop, after the redraw takes places. afterFinish is called after the last redraw of the effect was made. Callbacks are passed one argument, a reference to the effect object. For example:

<%= link_to_function "Fade with callback",       "new Effect.Fade('target', { afterUpdate: function(effect) {          effect.element.innerHTML = effect.currentFrame;        }})" %>

Chapter 11 covers Effect callbacks in more detail.

4.1.5. Transitions

The transition option determines the pattern of changea constant linear rate of change, gradual speed up, or anything else. There are eight standard transitions, and you can easily define new ones. To override the default transition for an effect, use the transition option like this:

<%= link_to_function "Fade with wobble",       "new Effect.Fade('target',          { transition: Effect.Transitions.wobble })" %>

The available transitions are: linear, reverse, none, full, sinoidal, pulse, wobble, and flicker. Chapter 11 describes them in detail and explains how to create custom transitions. To get a feel for the possibilities, create a demo for yourself of each transition:

<% %w( linear reverse none full sinoidal pulse         wobble flicker ).each do |name| %>   <%= link_to_function "Fade with #{name}",         "new Effect.Fade('target',           { transition: Effect.Transitions.#{name} })" %> <% end %>

4.1.6. Visual Effect Helper

So far, we've been using script.aculo.us's Effect object directly, without the aid of Rails helpers. Rails also provides a helper to generate visual effects, allowing you to create effects without writing JavaScript. The helper is visual_effect, and it's used like this:

visual_effect(:fade, :target)

The first argument is the name of a script.aculo.us effect (almostsee the note below), and the second is the ID of a DOM element. The visual_effect helper outputs a JavaScript snippet, so it's usually used in combination with another helper, like link_to_function:

<li><%= link_to_function "Fade", visual_effect(:fade, :target) %></li>

The toggle effects can be used from the helper method as well:

<%= link_to_function "Toggle Blind",     visual_effect(:toggle_blind, :target) %>

Standard Ruby style is to use underscores to separate words in variable and method names. The script.aculo.us effect methods, on the other hand, follow the JavaScript convention of "CamelCase." So when you are using the visual_effect helper, remember to use the lower-case, underscored versions of the effect names; e.g., BlindUp becomes blind_up.


The visual_effect helper is especially useful when combined with Ajax helpers, such as link_to_remote. For example, you might use the Highlight effect to draw the user's attention to a portion of the page that has been updated via Ajax. To see it in action, first add a new action to chapter4_controller.rb:

def get_time   render :text => Time.now end

And then create an Ajax link to it in views/chapter4/index.rhtml:

<%= link_to_remote "Get Time",     :update   => "current_time",     :url      => { :controller => "chapter3", :action => "get_time" },     :complete => visual_effect(:highlight, :current_time) %> <div ></div>

Notice that, unlike the examples in the last chapter, we aren't writing custom JavaScript in the :complete optioninstead, we let the visual_effect helper write it for us.




Ajax on Rails
Ajax on Rails
ISBN: 0596527446
EAN: 2147483647
Year: 2006
Pages: 103
Authors: Scott Raymond

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net