Section 15.3. Visual Effects for That Wow Factor


15.3. Visual Effects for That "Wow Factor"

Though people ultimately use software because of the things the software will do for them, how people perceive the software will have a big impact on how they feel about it. People learn better and work better when they're having fun. Visual effects don't add anything tangible to your product (you don't get to add an extra bullet point for them!), but they can make a huge difference in how your users feel about your product.

The MochiKit.Visual module provides a number of easy-to-use visual effects routines. MochiKit.DragAndDrop gives you a simple way to add drag-and-drop controls to part of your application. MochiKit.Sortable lets you give your users a way to sort a list with drag and drop with only a couple lines of code. Together, these three modules let you ratchet up the overall feel of your application by a couple of notches.

15.3.1. Rounded Corners

We start with the most humble feature in the package: rounded corners. Generally, if you want a rounded-off look for your application, you need to resort to images that you slice up just right to achieve the effect. The Visual module lets you round the corners of an element (or collection of them) with a single call, no images required.

You can see the rounded-corners effect for yourself using MochiKit's interactive interpreter:

writeln(DIV({"class" : "rounded", "style" :     "text-align:center; background:black; color: white"},     "Square edge or round, you decide!"));


That command gives us a white-on-black <DIV> element, with the traditional squared-off corners. Now run this:

roundClass("div", "rounded");


Our <DIV> now looks rounded. That call said to make any <DIV> elements with the class rounded be rounded off. You can pass in null for either the tag or the class to match all tags or classes.

Some caveats apply to using the rounded elements feature: It only works properly on "block" nodes and can be thrown off by padding.

In addition to roundClass, there is also a roundElement function that lets you round a specific DOM node.

Both roundClass and roundElement have an optional additional parameter of an options object. The options available for rounding are found in Table 15.2.

Table 15.2. Corner Options

Option

Description

corners

Which corners should be rounded. This can be all, top, bottom, tl (top left), bl (bottom left), tr (top right), br (bottom right). The default is all.

color, bgColor

Determine whichh colors should be used for the border that is created. color defaults to fromElement and bgColor defaults to fromParent, and you can use any color specification that's valid in CSS.

blend

Should the color and background color be blended together to produce the border color? The default is true.

compact

Yields a smaller border with small rounded corners.


This feature was ported from OpenRico to MochiKit, so you may be able to find additional information regarding rounded corners at the OpenRico site: http://openrico.org/.

15.3.2. Getting Started with Effects

Visual lets you provide a nicer-looking experience right away. Give this a whirl in your interpreter. (Reload the page if you already had one open: otherwise, you'll have scrolling issues.)

writeln(DIV({"id" : "nowyouseeit"}, "Now you don't!"));


That puts a simple <div> up for you to play with. Let's make it disappear and then reappear, using functions we talked about earlier in the chapter:

hideElement("nowyouseeit"); showElement("nowyouseeit");


As expected, the element appears and then disappears, each transition happening in an instant. Compare that with this:

toggle("nowyouseeit"); toggle("nowyouseeit");


toggle(element[, effect[, options]]) will do a nice, simple fade in/fade out by default. It's simple, but sometimes more pleasing than having an element abruptly disappear. effect can be one of slide, blind, appear, and size. try those out, and you'll see that you can get pretty flashy without much fuss.

15.3.3. Effect Options

All the visual effects take an "options" parameter, which is an object that provides, you guessed it, options for the effects. There are a number of standard options, and their default values can be found in MochiKit.Visual.DefaultOptions.

The standard options and their default values are listed in Table 15.3.

Table 15.3. Standard Effect Options

Option

Default Value

Description

transition

MochiKit.Visual.Transitions.sinoidal

This is how the values for the transitions should be computed. Other transitions to try out in MochiKit.Visual.transitions: flicker and pulse.

duration

1.0 (seconds)

Length of time for which the effect will run.

fps

25.0

This is how many frames per second the effect should use. In other words, how many values should the effect compute per second. The larger the number, the smoother the effect, but the more likely it is to slow down the user's computer, and the less you're likely able to do in parallel.

sync

false

By default, an effect will render its frames automatically. If `sync` is `false`, you can manually call the `render` method to control the timing of the effect. This is how the `Parallel` effect works.

from

0.0

Starting time for the effect, which is handy if you're coordinating multiple effects.

to

1.0

Ending time for the effect.

delay

0.0

Sets a fraction of the duration to wait before the effect actually kicks in. Set to 0.5, it will wait for half the duration and then start displaying the effect.

queue

`parallel`

By default, if you create multiple effects at once, they will all run at the same time (in parallel). You can also specify that you want a given effect to be at the `start` or `end` of the queue for the page, to easily allow effects to appear sequentially.


You can see the options in action for yourself with the toggle function we've already looked at:

toggle("nowyouseeit", "appear", MochiKit.Visual.Transitions.pulse);


If you have multiple interrelated elements, you can run the same effect on all of them in parallel:

>>> writeln(DIV({"id":"one"}, "The First Element")); The First Element >>> writeln(DIV({"id":"two"}, "The Second Element")); The Second Element >>> multiple(["one", "two"], fade);


15.3.4. The Core Effects

These effects are the building blocks for more-complicated effects. They are "classes," so you need to use new to use them. The general form used for all the effects, which we've already seen, is effect(element[, options]). For the core effects, you use new Effect(element[, options]), the one deviation from this in the standard set is Scale which also requires a percent parameter to be useful.

Highlight gives you the famous Yellow Fade technique. By default, a yellow background fades in and then disappears. Of course, you can change the color with the startcolor option.

The Scale(element, percent[, options]) effect has several options and an extra parameter. The percent parameter specifies how much you would like the element to scale by. The other options offered for the Scale effect are listed in Table 15.4.

Table 15.4. Options for the Scale Effect

Option

Default Value

Description

scaleX

TRue

Whether or not to scale on the X axis.

scaleY

true

Whether or not to scale on the Y axis.

scaleContent

true

Are you scaling just the box or the content as well?

scaleMode

`box`

By default, scaling is based on the visible area of the element. If you set scaleMode to contents, then the parts that are not in the visible area of the browser window will also be taken into account. If scaleMode is an object with originalHeight and originalWidth attributes, you can precisely define what the original size of the element was for use in the effect.

scaleFrom

100.0

What percentage of the size are you starting at?

scaleTo

`percent`

What percentage should the scaling end at.


Another class that is offered is Parallel(effects[, options]), which launches the provided effects in parallel.

The remaining core effects all have fewer options, as summarized here:

  • Opacity Change the opacity of the element with from and to options that default to 0.0 and 1.0, respectively.

  • Move Change the position of an element with x and y options that default to 0. There's also a position option (relative) to specify whether x and y are relative or absolute positions.

  • ScrollTo Scrolls the window to the position of the given element, providing a smooth scrolling effect rather than an instantaneous repositioning.

15.3.5. Combination Effects

The "combination effects" build on the core effects to provide easy-to-use functions that have a polished and complete look. All of these functions have the signature effect(element[, options]). The combination effects are as follows:

  • fade Change the opacity of the element until it disappears with from and to options. from defaults to getOpacity(element) or 1.0 if that is not set. to defaults to 0.0.

  • appear The reverse of fade.

  • puff The element will double in size and then disappear.

  • blindUp The element's vertical size will shrink to 0, giving the effect of a blind rolling up.

  • blindDown The reverse of blindUp.

  • switchOff The element will shrink to nothing in the middle (reminiscent of a television set that shows a bright line in the middle of the screen before it turns off).

  • dropOut The element will fall straight down and fade.

  • shake The element shakes from left to right (but stays on the screen).

  • slideDown The element will slide down.

  • slideUp The element will slide up.

  • squish The element shrinks horizontally and vertically, starting with the upper-left corner, leaving nothing behind.

  • grow Restore the size of an element.

  • shrink The element slides to the right and shrinks to nothing as it goes.

  • pulsate The element appears and fades repeatedly. (The element remains visible at the end.)

  • fold Reduce the vertical size and then the horizontal size, leaving nothing behind.

15.3.6. Customizing Effect Behavior

The effect options described earlier in the chapter provide a number of ways you can customize the appearance of an effect, but they don't change the fundamental behavior of the effect. You can also change the behavior of an effect via options by setting callbacks for events that occur during an effect's lifetime. The events are as follows:

  • beforeStart

  • beforeSetup

  • beforeUpdate

  • afterUpdate

  • beforeFinish

  • afterFinish

A simple example will chain two effects:

writeln(DIV({"id" : "shaker"}, "Pulsate and shake!")); pulsaste("shaker", {"afterFinish" : function() { shake("shaker"); } } }


You can also create your own, new effects based on the MochiKit.Visual.Base class. You can override the setup, update, and finish methods to design an effect that does whatever you want.

As an example of a completely custom effect, we'll make a "rolling sign" effect that roughly simulates those signs that keep changing letters around until they reach the final desired text. This is visually similar to that, but the intermediate letters that are chosen are completely random:

You can try this code out easily in the interpreter after you've entered it:

writeln(DIV({id:"hiya"}, "Hey there!")); new RollingSign("hiya", "That's all folks!");


You can also try tweaking standard options, such as duration, to see the effect they have.

Learning More about the Visual Effects

The visual effects in MochiKit.Visual were ported from Scriptaculous, which uses the Prototype JavaScript library as its basis. While you could just use Scriptaculous alongside of MochiKit, there have historically been compatibility problems between Prototype and other JavaScript libraries. MochiKit is designed to be very unobtrusive and compatible, and by porting Scriptaculous' effects to a MochiKit basis you gain that level of compatibility, plus you're able to work with MochiKit's other great features.

Scriptaculous is a popular package. The advantage to porting Scriptaculous rather than coming up with new APIs strictly for MochiKit is that many of the articles and add-on effects for Scriptaculous will readily apply for use with MochiKit.

You can find add-on effects and more information at http://script.aculo.us and web searches with "scriptaculous" for specific topics usually yield useful results.


15.3.7. An Effects Demo

Two more packages have also been ported from Scriptaculous: DragAndDrop and Sortable. Both of these let you provide a drag-and-drop (DND) user interface for your application with a minimum of fuss. DND is an important user interface feature because certain types of UI problems are not solved gracefully through any other means on the web.

One example of this is an "ordered list of items." Consider an election system where you don't just pick a single candidate, but instead need to put the candidates in order of preference. The "old-fashioned" way to do this in a web browser was a setup involving a "select multiple" control and up and down buttons. You'd select someone from the list and repeatedly click the up or down button until that person was in the right place. Then you'd painstakingly repeat the process until you were done, or until you just gave up and let the other guy win.

DND is much more natural for this. Just drag the person up to the spot where you want the person to be. Simple. Note that DND on the web is not likely to work with accessibility solutions for disabled users. You might still consider offering some kind of up and down buttons for that reason. Yahoo!'s My Yahoo service, for example, lets you drag and drop modules on your My Yahoo page, but also offers a separate, old-style page that is doubtless more accessible.

Ordered lists are such a common requirement that Scriptaculous/MochiKit offer something called a Sortable. A Sortable provides prepackaged, ready-to-run DND for ordered lists. As an example of this, we'll use an effects viewer that lets you view MochiKit's visual effects individually or create an ordered chain of effects that are run one after the other.

There are two things to note about this demo before we look at the code. As of this writing, MochiKit.Visual is not yet complete. The API is not likely to change much, but the packaging might change some. At present, the packed MochiKit.js distribution does not include New.js, DragAndDrop.js, or Sortable.js. This packaging issue will undoubtedly be resolved by the time MochiKit 1.4 ships. In addition, the Sortable name is not exported by the Sortable.js module. So, you'll note in the following code that we refer directly to MochiKit.Sortable.Sortable. That style of access will continue working later on, so feel free to use it. It's just a bit wordier.

And now, on to the Effects/Sortable/DND sample.

This demo program, pictured in Figure 15.2, enables you to watch a number of MochiKit's effects as they're applied to the header of the page. You can set the duration and then click a button to see the effect. You can also view the RollingSign effect implemented in the preceding section.

Figure 15.2. Effects Picture


Sortable comes in with the "effects chain" feature of the page. You can grab on to the green handles and drag effects from the left side of the page into the effects chain box. You can also change the ordering of the effects. That box will run the effects one after another in the same order in which the buttons appear on the page. It's a nifty bit of functionality, and you'll see that it's done with very little code:

15.3.8. Sortables and DragAndDrop

One call to Sortable.create packs a lot of power! Sortable.create(element[, options]) takes an element (generally a ul) and a variety of options. Many of the options come straight from the DragAndDrop package, on which Sortable builds. Let's talk about the lower-level DND package before getting to the details of Sortable.

DND provides you with two kinds of objects: Draggables and Droppables. They have the familiar-looking signatures new Draggable(element[, options]) and new Droppable(element[, options]). To allow an element to be picked up and dragged around the page is as simple as new Draggable('elementid'). However, you might want to change a number of options that affect the draggable's behavior. These options are listed in Table 15.5.

Table 15.5. Options for a Draggable Element

Option

Default Value

Description

handle

false

By default, the user can grab anywhere on the draggable element to start dragging it around. If you provide either a CSS class name or an element ID as the handle option, the user can grab the matching elements to drag them around.

starteffect

MochiKit.Visual.Opacity

When the drag is started, this callback is called with the element that is being dragged. Typically, this is an effect that you want to apply to the element.

revert

false

If true, the revert effect is called when the user releases the draggable somewhere other than an appropriate drop target.

revert-effect

MochiKit.Visual.Move

If you have the revert option set to true, this effect is called to return the draggable back to its original position.

endeffect

MochiKit.Visual.Opacity

Effect that will reverse the effect that was put on by the starteffect.

zindex

1000

CSS z-index for the element while it is being dragged. The default should put the element in front of every other element.

snap

false

Defines the behavior of the draggable while it's being dragged. It can be a function, a value, or an array of two values. As a function, it takes the (x,y) position as arguments and returns the position to draw in the browser. If it's a single value, it's used as a modulo for the x and y values. If it's a two-element array, a[0] is used as the modulo for the x-axis, and y[0] is used as the modulo for the y value.

selectclass

null

CSS class to be applied while the element is being dragged.

ghosting

false

If true, a "ghostlike" transparency will be applied to the element as it is dragged.

onchange

MochiKit.Base.noop

As the element is dragged, this function is called with the Sortable as its parameter.

scroll

false

Element in which the draggable can scroll around. For example, "window" will let it scroll around within the window.

scrollSensitivity

20

How quickly does the scroll speed increase as you get closer to the edges of the screen.

scrollSpeed

15

How fast does the scrolling move.

constraint

null

If set to horizontal or vertical, this will restrict the movement of this draggable to only the specified axis.


Wow! That's a lot of options! And that's just the draggable. It is, indeed, a lot of options. The DND module provides lower-level services and is set up to handle just about any drag-and-drop needs your application might have. It's quite easy to make an element draggable (new Draggable('elementid') is all it takes), but you'll likely spend a fair bit of time tweaking the behavior until it's exactly what you want it to be.

Let's take a look at the options available for a droppable, as listed in Table 15.6.

Table 15.6. Options for a Droppable Element

Option

Default

Description

greedy

true

MochiKit will stop looking for other droppables when a draggable is over this one.

hoverclass

null

The CSS class to apply when a draggable is hovering over this droppable.

hoverfunc

MochiKit.Base.noop

Called when a draggable starts or stops hovering over this droppable. The function is passed the draggable and true if the hovering has just started, false if the draggable has just been dragged off of the droppable.

accept

null

Array of CSS classes that draggables must have in order to be allowed to drop on this element. `null` means that no specific class is required.

activeclass

null

CSS class applied.

onactive

MochiKit.Base.noop

When a draggable first comes over this droppable, this function will be called. This function is passed the droppable and the draggable as parameters.

containment

[]

This droppable will only accept a draggable that is either set as the value for containment or as one of the values in an array that is set as containment. Sortable uses this to control dragging behavior between Sortables.

onhover

MochiKit.Base.noop

This function is called as a draggable is moved over a droppable. It is passed three parameters: the draggable, the droppable, and a percentage of overlap.

ondrop

MochiKit.Base.noop

When a draggable is dropped, this function is called. It takes three arguments: the draggable, the droppable, and the event that resulted in the drop.


Using the draggable and droppable classes, you have a large amount of control over how the drag-and-drop experience looks (via CSS that is applied at various points) and acts (via the effects and callbacks). As you saw from the effects demo, the specific case of making a list of items that is sortable via DND has a high-level interface. Using Sortable, you don't need to worry about all the different event possibilities.

The options for Sortables can be found in Table 15.7.

Table 15.7. Options for Sortable Elements

Option

Default

Description

tag

"li"

Which tag your user can move around.

dropOnEmpty

false

Can you drop items on the list if there's nothing in the list?

overlap

"vertical"

The draggable needs to be overlapping by at least 50% in this direction in order to be droppable.

only

null

An element must have one of the CSS classes specified in only in order to be movable in the list.

format

/^[^_]*_(.*)$/

This regular expression is used for serialization based on the children's IDs. Using the default regular expression with ID values such as foo_1, foo_2 and foo_3, you'll get back [1, 2, 3] as the values.

onChange

MochiKit.Base.noop

Called whenever the order of the sortable changes, even if the draggable isn't dropped into a new position.

onUpdate

MochiKit.Base.noop

Called after an element is dropped on the sortable.

tree

false

Makes a sortable tree. As of this writing, there is a warning in the MochiKit documentation that the speed of this feature becomes quickly unacceptable, so this is an experimental feature.


The features outlined in previous sections of this chapter enable you to craft powerful, interactive, web-based applications with far less effort than in years past. MochiKit's effects, combined with Sortable and DND functionality, can help put a serious shine on your application, giving it a modern look and feel that will delight your users. Have fun with it without overdoing it, and your users will love you for it.




Rapid Web Applications with TurboGears(c) Using Python to Create Ajax-Powered Sites
Rapid Web Applications with TurboGears: Using Python to Create Ajax-Powered Sites
ISBN: 0132433885
EAN: 2147483647
Year: 2006
Pages: 202

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