Chapter 5. Sprucing up with animations and effects

This chapter covers

  • Showing and hiding elements without animations
  • Showing and hiding elements using core jQuery animated effects
  • Other built-in effects
  • Writing our own custom animations

Have you ever looked at a website built in Flash and become envious because of all the pretty effects that Flash developers have at their disposal? Heck, you might have even become tempted to learn Flash purely for those slick effects.

Not long ago, smooth effects and animations weren’t realistic options using JavaScript. Between cross-browser issues and slow browser implementations, trying to fade or zoom elements, or even move them around the screen, was extraordinarily difficult. Thankfully, that state of affairs has passed, and jQuery provides a trivially simple interface for doing all sorts of neat effects.

But before we dive into adding whiz-bang effects to our pages, we need to contemplate the question: should we? Like a Hollywood blockbuster that’s all special effects and no plot, a page that overuses effects can elicit the opposite reaction than we intended. Be mindful that effects should be used to enhance the usability of a page, not hinder it.

With that caution in mind, let’s see what jQuery has to offer.

5.1. Showing and hiding elements

Perhaps the most common type of dynamic effect we’ll want to perform on an element or group of elements is the simple act of showing or hiding them. We’ll get to more fancy animations (like fading an element in or out) in a bit, but sometimes we want to keep it simple and pop elements into existence or make them vanish!

The commands for showing and hiding elements are pretty much what we’d expect: show() to show the elements in a wrapped set and hide() to hide them. We’re going to delay presenting their formal syntax for reasons that will become clear in a bit; for now, let’s concentrate on using these commands with no parameters.

As simple as these methods may seem, we should keep a few things in mind. First, jQuery hides elements by changing the display value of the style property to none. If an element in the wrapped set is already hidden, it will remain hidden but still be returned for chaining. For example, suppose we have the following HTML fragment:

<div style="display:none;">This will start hidden</div>
<div>This will start shown</div>

If we apply $("div").hide().addClass("fun"), we’ll end up with the following:

<div style="display:none;" class="fun">This will start hidden</div>
<div style="display:none;" class="fun">This will start shown</div>

Second, if an element starts as hidden by having its display style property value explicitly set to none, the show() command will always set its display style property value to block. That’s even if the element would typically default to inline for its display value—as would a <span> element, for example. If the element starts out without an explicitly declared display value, and we use the jQuery hide() command to hide it, the show() command will remember the original value and restore it to that original display state.

So it’s usually a good idea not to use style attributes on the elements we want initially hidden, but to apply the hide() command to them in the page’s ready handler. This prevents them from being displayed on the client, and also makes sure everything is in a known initial state and will behave as expected during subsequent hide and show operations.

Let’s see about putting these commands to good use.

5.1.1. Implementing a collapsible list

Inundating a user with too much information at once is a common and classic user interface boo-boo. It’s best to allow users to ask for information in digestible chunks that are under their control. This is a tiny glimpse into a larger principle known as progressive disclosure (which we were introduced to in the previous chapter) in which the data presented to users is kept to the minimum and expanded as required to perform the task at hand.

A good example of this might be browsing the filesystem of a computer. This information is frequently presented as a hierarchical list in which the content of folders is nested to the depth required to represent all files and folders on the system. It would be ludicrous to try to present all the files and folders on the system at once! A better approach is to allow each level in the list to be opened or closed to reveal the contained hierarchical information. You’ve surely seen such controls in any application that allows you to browse the filesystem.

In this section, we’ll see how to use the hide() and show() commands to instrument a nested list that acts in this manner.


Note

There are some nifty plugins that provide this type of control out-of-the-box if, once you understand the principles behind it, you’d rather use a ready-made solution than write your own.


To start, let’s take a look at the HTML structure of the list we’ll use to test our code.

<body>
<fieldset>
<legend>Collapsible List &mdash; Take 1</legend>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>
Item 3
<ul>
<li>Item 3.1</li>
<li>
Item 3.2
<ul>
<li>Item 3.2.1</li>
<li>Item 3.2.2</li>
<li>Item 3.2.3</li>
</ul>
</li>
<li>Item 3.3</li>
</ul>
</li>
<li>
Item 4
<ul>
<li>Item 4.1</li>
<li>
Item 4.2
<ul>
<li>Item 4.2.1</li>
<li>Item 4.2.2</li>
</ul>
</li>
</ul>
</li>
<li>Item 5</li>
</ul>
</fieldset>
</body>

Note

Because this section focuses on the effects, let’s assume the list we’ll instrument is small enough to send completely as part of the page. Obviously, this would not be true for something as massive as the data set for an entire filesystem. In such cases, you’d want to go back to the server for more and more data as you need it, but that’s not what we want to focus on in this chapter. After you’ve read the Ajax chapter, you can revisit these examples and apply your skills to enhance these controls with such abilities.


When displayed in the browser (prior to tinkering with it), this list appears as shown in figure 5.1.

Figure 5.1. The nested list before we get our hands on it

A list of this size is relatively easy to digest, but it’s easy to imagine it getting longer and deeper, in which case presenting the full list to users could cause them to suffer from the dreaded Information Overload Syndrome.

We want to instrument all list items that contain another embedded list so that the embedded content is hidden until the users choose to view it by clicking the item. After such a click, the child content of the item will be revealed, and a subsequent click will hide the contents again.

If we only hide the content of items that contain child lists (items 3 and 4 of the topmost list, for example), we’d likely confuse the users because they’d have no way of knowing these items are active and expandable; we need to visually distinguish these expandable items from those that are leaf items (those that can’t be expanded). We do that by changing the cursor to the hand when it passes over an active item, as well as replacing its list marker with the ubiquitous plus- and minus-sign graphics to indicate that the item can be either expanded or collapsed.

We’ll start the list off in its fully collapsed state and let the users take it from there. After instrumentation, the list will appear as shown in figure 5.2 when initially displayed.

Figure 5.2. After instrumentation, the list has been fully collapsed and the expandable items are visually distinct.

We can see that for the list items that have content (items 3 and 4) the following occurs:

  • The children of the list items 3 and 4 are hidden.
  • The list markers for the items have been replaced with a plus-sign graphic to indicate that the item can be expanded.
  • The mouse cursor changes to the hand when it hovers over these items.

Clicking these active items reveals their children as shown in the series of displays in figure 5.3.

Figure 5.3. Clicking active elements causes their contents to be revealed.

Let’s examine how we apply this behavior to the DOM elements of the list, setting it up within the ready handler, as shown in listing 5.1.

Listing 5.1. Ready-handler code that instruments the list with expandable behavior

There isn’t a whole lot of code to this ready handler, but there is a lot of activity.

First, we select all list items that possess list children by applying the jQuery containment selector li:has(ul) , and apply a chained series of jQuery commands to the matched elements, beginning with attaching a click handler .

This click handler checks to make sure that the target element of the event matches this. This is true only when the clicked item is the same as the one on which the listener was established; it allows us to ignore clicks on the child elements. After all, we only want to open and close an item when users click the parent item, not one of its children.

If we determine that a parent item has been clicked, we then determine if its children are hidden or shown by employing the handy is() command using the :hidden filter . If the children are hidden, we reveal them using show(), and if shown, we hide them using hide(). In either case, we change the parent item marker to the plus or minus image (as appropriate) and return false as the value of the listener to prevent needless propagation.

We set the mouse cursor shape to the active pointer using the css() command and hide the child elements for the active items, performing the actions defined within the else clause of the if statement in the click handler, by invoking the click handler .

As the final step before users can interact with the page, we need to sledgehammer some styling elements for the leaf items . We’ve set the list-style-image style (which controls the item marker) of the active items to one of the plus or minus GIF images, and we don’t want that setting to be inherited by the list items that are children of those items. To prevent that inheritance, we explicitly set that list-style-image style property value to none for all leaf list items. Because we have set it directly on the items, it will take precedence over any inherited value.

We do the same for the mouse cursor for the leaf items by setting it to the default mouse cursor shape. Otherwise leaf items contained by an active parent would inherit the active cursor shape.

The full code for this page can be found in file chapter5/collapsible.list.take.1.html. (If you surmise that the take 1 part of this name indicates that we’ll be revisiting this example, you’re right!)

That wasn’t too difficult for the amount of functionality enabled, but as it turns out, it can be even easier.

5.1.2. Toggling the display state of elements

Toggling the display state of elements between revealed or hidden—as for the collapsible list example—is such a common occurrence that jQuery defines a command named toggle() that makes it even easier.

Let’s apply this command to the collapsible list and see how it helps to simplify the previous code. Listing 5.2 shows only the ready handler for the refactored page (no other changes are necessary) with the new changes highlighted in bold. The complete page code can be found in file chapter5/collapsible.list.take.2.html.

Listing 5.2. Changes to the collapsible list to use the toggle() command
$(function(){
$('li:has(ul)')
.click(function(event){
if (this == event.target) {
$(this).children().toggle();
$(this).css('list-style-image',
($(this).children().is(':hidden')) ?
'url(plus.gif)' : 'url(minus.gif)'),
}
return false;
})
.css('cursor','pointer')
.click();
$('li:not(:has(ul))').css({
cursor: 'default',
'list-style-image':'none'
});
});

Note that we no longer need the conditional statement to determine whether to hide or show the elements; toggle() takes care of swapping the displayed state. We still use the .is(':hidden') test as part of a simpler ternary expression to determine the appropriate image to use for the item marker.

Instantaneously making elements appear and disappear is handy, but sometimes we want the transition to be less abrupt. Let’s see what’s available for that.

5.2. Animating the display state of elements

Human cognitive ability being what it is, making items pop into and out of existence instantaneously can be jarring to us. If we blink at the wrong moment, we could miss the transition, leaving us to wonder, “What just happened?”

Gradual transitions of a short duration help us know what’s changing and how we got from one state to the other. And that’s where the jQuery core effects come in, of which there are three sets:

  • Show and hide (there’s a bit more to these commands than we let on in section 5.1)
  • Fade in and fade out
  • Slide down and slide up

Let’s look more closely at each of these effect sets.

5.2.1. Showing and hiding elements gradually

The show(), hide(), and toggle() commands are more complex than we led you to believe in the previous section. When called with no parameters, these commands effect a simple manipulation of the display state of the wrapped elements, causing them to instantaneously be revealed or hidden from the display. But when passed parameters, these effects can be animated so that their changes in display status take place over a period of time.

Now we’re ready to look at the full syntaxes of these commands.


Command syntax: hide

hide(speed,callback)

Causes the elements in the wrapped set to become hidden. If called with no parameters, the operation takes place instantaneously by setting the display style property value of the elements to none. If a speed parameter is provided, the elements are hidden over a period of time by adjusting their size and opacity downward to zero, at which time their display style property value is set to none to remove them from the display.

An optional callback can be specified that’s invoked when the animation is complete.

Parameters

speed

(Number|String) Optionally specifies the duration of the effect as a number of milliseconds or as one of the predefined strings: slow, normal, or fast. If omitted, no animation takes place, and the elements are immediately removed from the display.

callback

(Function) An optional function invoked when the animation completes. No parameters are passed to this function, but the function context (this) is set to the element that was animated.

Returns

The wrapped set.



Command syntax: show

show(speed,callback)

Causes any hidden elements in the wrapped set to be revealed. If called with no parameters, the operation takes place instantaneously by setting the display style property value of the elements to their previous setting (such as block or inline) if the element was hidden via a jQuery effect. If the element was not hidden via jQuery, the display style property value defaults to block.

If a speed parameter is provided, the elements are revealed over a specified duration by adjusting their size and opacity upward.

An optional callback can be specified that’s invoked when the animation is complete.

Parameters

speed

(Number|String) Optionally specifies the duration of the effect as a number of milliseconds or as one of the predefined strings: slow, normal, or fast. If omitted, no animation takes place and the elements are immediately revealed in the display.

callback

(Function) An optional function invoked when the animation is complete. No parameters are passed to this function, but the function context (this) is set to the element that was animated.

Returns

The wrapped set.



Command syntax: toggle

toggle(speed,callback)

Performs show() on any hidden wrapped elements and hide() on any non-hidden wrapped elements. See the syntax description of these commands for their respective semantics.

Parameters

speed

(Number|String) Optionally specifies the duration of the effect as a number of milliseconds or as one of the predefined strings: slow, normal, or fast. If omitted, no animation takes place.

callback

(Function) An optional function invoked when the animation is complete. No parameters are passed to this function, but the function context (this) is set to the element that was animated.

Returns

The wrapped set.


Let’s do a third take on the collapsible list, animating the opening and closing of the sections.

Given the previous information, you’d think that the only change we need to make to the code of take 2 of this collapsible list implementation would be to change the call to the toggle() command to

toggle('slow')

But not so fast! When we make this change and test the page, we’ll notice some weird things going on. First, recall that, in order to initially hide the collapsible elements, we called the click handler of the active items. That was well and good when all the handler did was to immediately hide the child elements. But now we’ve animated that activity; when the page loads, we see the child items hiding themselves in the animated fashion. That won’t do at all!

We need to explicitly use the hide() command, without parameters, to hide the element before the user gets a chance to see them and then to set the markers to the plus image. You’ll recall that we didn’t do that in the earlier example because it would have created repeated code. Well, with the changes we’ve made, that’s no longer an issue.

The second problem we’d notice is that marker images no longer act correctly. When the toggle action was instantaneous, we could safely check for the results of the action immediately after it took place. Now that the toggle action is animated, its results are no longer synchronous, and checking afterward for whether the children are hidden or not (in order to know which image the marker should be set to) is no longer possible.

Let’s invert the sense of the test and check the state of the children before we issue the animated toggle.

The new ready handler, with changes highlighted in bold, is shown in listing 5.3.

Listing 5.3. Our list example augmented with the animated effects
$(function(){
$('li')
.css('pointer','default')
.css('list-style-image','none'),
$('li:has(ul)')
.click(function(event){
if (this == event.target) {
$(this).css('list-style-image',
(!$(this).children().is(':hidden')) ?
'url(plus.gif)' : 'url(minus.gif)'),
$(this).children().toggle('slow'),
}
return false;
})
.css({cursor:'pointer',
'list-style-image':'url(plus.gif)'})
.children().hide();
$('li:not(:has(ul))').css({
cursor: 'default',
'list-style-image':'none'
});
});

The page with these changes can be found in file chapter5/collapsible.list.take.3.html.

Knowing how much people like us love to tinker, we’ve set up a handy tool that we’ll use to further examine the operation of these commands.

Introducing the jQuery Effects Lab Page

Back in chapter 2, we introduced the concept of lab pages to help us experiment with using jQuery selectors. For this chapter, we set up a lab page for exploring the operation of the jQuery effects in file chapter5/lab.effects.html.

Loading this page into your browser results in the display shown in figure 5.4.

Figure 5.4. The initial state of the jQuery Effects Lab Page, which will help us examine the operation of the jQuery effects commands

This lab page consists of two main panels: a control panel in which we’ll specify which effect will be applied and one that contains four test subject elements upon which the effects will act.

“Are they daft?” you might be thinking. “There are only two test subjects.”

No, your authors haven’t lost it yet. There are four elements, but two of them (another <div> with text and another image) are initially hidden.

Let’s use this page to demonstrate the operations of the commands we’ve discussed to this point. Display the page in your browser, and follow along with the ensuing exercises:

  • Exercise 1— With the controls left as is after the initial page load, click the Apply button. This will execute a show() command with no parameters. The command that was applied is displayed below the Apply button for your information. Note how the two initially hidden test subject elements appear instantly. If you’re wondering why the image on the far right appears a bit faded, its opacity has been purposefully set to 50 percent.
  • Exercise 2— Select the Hide radio button, and click Apply to execute a parameterless hide() command. All of the test subjects vanish. Take special notice that the fieldset in which they reside has tightened up. This indicates that the elements have been completely removed from the display rather than made invisible.
    Note

    When we say that an element has been removed from the display (here, and in the remainder of our discussion about effects), we mean that the element is no longer being taken into account by the browser’s layout manager, just as if its CSS display style property value has been set to none. It does not mean that the element has been removed from the DOM tree; none of the effects will ever cause an element to be removed from the DOM.


  • Exercise 3— Next, select the Toggle radio button, and click Apply. Click Apply again. And again. You’ll note that each subsequent execution of toggle() flips the presence of the test subjects.
  • Exercise 4— Reload the page to reset everything to the initial conditions (in Firefox, set focus to the address bar and hit the Enter key). Select Toggle, and click Apply. Note how the two initially visible subjects vanish and the two that were hidden appear. This demonstrates that the toggle() command applies individually to each wrapped element, revealing the ones that are hidden and hiding those that aren’t.
  • Exercise 5— In this exercise, let’s move into the realm of animation. Refresh the page, and for the Speed setting, select Slow. Click Apply, and carefully watch the test subjects. The two hidden elements, rather than popping into existence, gradually grow from their upper left corners. If you want to see what’s going on, refresh the page, select Milliseconds for the speed and enter 10000 for the speed value. This will extend the duration of the effect to 10 (excruciating) seconds and give you plenty of time to observe the behavior of the effect.
  • Exercise 6— Choosing various combinations of Show, Hide, and Toggle, as well as various speeds, experiment with these effects until you feel you have a good handle on how they operate.

Armed with the jQuery Effects Lab Page, and the knowledge of how this first set of effects operates, let’s take a look at the next set of effects.

5.2.2. Fading elements into and out of existence

If you watched the operation of the show() and hide() effects carefully, you noted that they scaled the size of the elements (either up or down as appropriate) and adjusted the opacity of the elements as they grew or shrank. The next set of effects, fadeIn() and fadeOut(), only affect the opacity of the elements.

Other than the lack of scaling, these commands work in a fashion similar to show() and hide() (when animated) respectively. The syntaxes of these commands are as follow:


Command syntax: fadeOut

fadeOut(speed,callback)

Causes any matched elements that aren’t hidden to be removed from the display by gradually changing their opacity to 0% and then removing the element from the display. The duration of the change in opacity is determined by the speed parameter. Any elements that are already hidden aren’t affected.

Parameters

speed

(Number|String) Specifies the duration of the effect as a number of milliseconds or as one of the predefined strings: slow, normal, or fast. If omitted, the default is normal.

callback

(Function) An optional function invoked when the animation completes. No parameters are passed to this function, but the function context (this) is set to the element that was animated.

Returns

The wrapped set.



Command syntax: fadeIn

fadeIn(speed,callback)

Causes any matched elements that are hidden to be shown by gradually changing their opacity to their natural value. This value is either the opacity originally applied to the element, or 100%. The duration of the change in opacity is determined by the speed parameter. Any elements that aren’t hidden aren’t affected.

Parameters

speed

(Number|String) Specifies the duration of the effect as a number of milliseconds or as one of the predefined strings: slow, normal, or fast. If omitted, the default is normal.

callback

(Function) An optional function invoked when the animation completes. No parameters are passed to this function, but the function context (this) is set to the element that was animated.

Returns

The wrapped set.


Let’s have some more fun with the jQuery Effects Lab Page. Display the lab, and run through a set of exercises similar to those we followed in the previous section using the Fade In and Fade Out selections (don’t worry about Fade To for now, we’ll attend to that soon enough).

It’s important to note that when the opacity of an element is adjusted, the jQuery hide(), show(), fadeIn(), and fadeOut() effects remember the original opacity of an element and honor its value. In the lab page, we purposefully set the initial opacity of the image at the far right to 50 percent before hiding it. Throughout all the opacity changes that take place when applying the jQuery effects, this original value is never stomped on.

Run though additional exercises in the lab until you’re convinced that this is so and are comfortable with the operation of the fade effects.

Another effect that jQuery provides is via the fadeTo() command. This effect adjusts the opacity of the elements like the previously examined fade effects, but never removes the elements from the display. Before we start playing with fadeTo() in the lab, here’s its syntax.


Command syntax: fadeTo

fadeTo(speed,opacity,callback)

Adjusts the opacity of the wrapped elements from their current setting to the new setting specified by opacity.

Parameters

speed

(Number|String) Specifies the duration of the effect as a number of milliseconds or as one of the predefined strings: slow, normal, or fast. If omitted, the default is normal.

opacity

(Number) The target opacity to which the elements will be adjusted specified as a value from 0.0 to 1.0.

callback

(Function) An optional function invoked when the animation completes. No parameters are passed to this function, but the function context (this) is set to the element that was animated.

Returns

The wrapped set.


Unlike the other effects that adjust opacity while hiding or revealing elements, fadeTo() doesn’t remember the original opacity of an element. This makes sense because the whole purpose of this effect is to explicitly change the opacity to a specific value.

Bring up the lab page, and cause all elements to be revealed (you should know how by now). Then work through the following exercises:

  • Exercise 1— Select Fade To and a speed value slow enough for you to observe the behavior; 4000 milliseconds is a good choice. Now set the Fade to Opacity field (which expects a percentage value between 0 and 100, converted to 0.0 through 1.0 when passed to the command) to 10, and click Apply. The test subjects will fade to 10 percent opacity over the course of four seconds.
  • Exercise 2— Set the opacity to 100, and click Apply. All elements, including the initially semi-transparent image, are adjusted to full opaqueness.
  • Exercise 3— Set the opacity to 0, and click Apply. All elements fade away to invisibility, but note that once they’ve vanished, the enclosing fieldset does not tighten up. Unlike the fadeOut() effect, fadeTo() never removes the element from the display, even when it’s fully invisible.

Continue experimenting with the Fade To effect until you’ve mastered its workings. Then we’ll be ready to move on to the next set of effects.

5.2.3. Sliding elements up and down

Another set of effects that hide or show elements—slideDown() and slideUp()—also works in a similar manner to the hide() and show() effects, except that the elements appear to slide down from their tops when being revealed and to slide up into their tops when being hidden.

As with hide() and show(), the slide effects have a command that will toggle the elements between hidden and revealed: slideToggle(). The by-now-familiar syntaxes for these commands follow below.


Command syntax: slideDown

slideDown(speed,callback)

Causes any matched elements that are hidden to be shown by gradually increasing their vertical size. Any elements that aren’t hidden aren’t affected.

Parameters

speed

(Number|String) Specifies the duration of the effect as a number of milliseconds or as one of the predefined strings: slow, normal, or fast. If omitted, the default is normal.

callback

(Function) An optional function invoked when the animation completes. No parameters are passed to this function, but the function context (this) is set to the element that was animated.

Returns

The wrapped set.



Command syntax: slideUp

slideUp(speed,callback)

Causes any matched elements that aren’t hidden to be removed from the display by gradually decreasing their vertical size.

Parameters

speed

(Number|String) Specifies the duration of the effect as a number of milliseconds or as one of the predefined strings: slow, normal, or fast. If omitted, the default is normal.

callback

(Function) An optional function invoked when the animation completes. No parameters are passed to this function, but the function context (this) is set to the element that was animated.

Returns

The wrapped set.



Command syntax: slideToggle

slideToggle(speed,callback)

Performs slideDown() on any hidden wrapped elements and slideUp() on any non-hidden wrapped elements. See the syntax description of these commands for their respective semantics.

Parameters

speed

(Number|String) Optionally specifies the duration of the effect as a number of milliseconds or as one of the predefined strings: slow, normal, or fast. If omitted, no animation takes place.

callback

(Function) An optional function invoked when the animation completes. No parameters are passed to this function, but the function context (this) is set to the element that was animated.

Returns

The wrapped set.


Except for the manner in which the elements are revealed and hidden, these effects act similarly to the other show/hide effects. Convince yourself of this by displaying the jQuery Effects Lab Page and running through sets of exercises similar to those we applied to the other effects.

5.2.4. Stopping animations

We may have a reason now and again to stop an animation once it has started. This could be because a user event dictates that something else should occur or because we want to start a completely new animation. The stop() command will achieve this for us:


Command syntax: stop

stop()

Halts all animations that may be currently in progress for the elements in the matched set

Parameters

  • none

Returns

The wrapped set


Note that any changes that have already taken place for any animated elements will remain in effect. If we want to restore the elements to their original state, it’s our responsibility to put the CSS values back to their starting values using the css() method or similar commands.

Now that we’ve seen the effects built into core jQuery, let’s investigate writing our own!

5.3. Creating custom animations

The number of core effects supplied with jQuery is purposefully kept small (in order to keep jQuery’s core footprint to a minimum) with the expectation that plugins are available to add more animations at the page author’s discretion. It’s also a simple matter to write our own animations.

jQuery publishes the animate() wrapper method that allows us to apply our own custom animated effects to the elements of the wrapped set. Let’s take a look at its syntax.


Command syntax: animate

animate(properties,duration,easing,callback)

animate(properties,options)

Applies an animation, as specified by the properties and easing parameters, to all members of the wrapped set. An optional callback function can be specified that’s invoked when the animation is complete. An alternate format specifies a set of options in addition to the properties.

Parameters

properties

(Object) An object hash that specifies the end values that supported CSS styles should reach at the end of the animation. The animation takes place by adjusting the values of the style properties from the current value for an element to the value specified in this object hash.

duration

(Number|String) Optionally specifies the duration of the effect as a number of milliseconds or as one of the predefined strings: slow, normal, or fast. If omitted, no animation takes place.

easing

(String) The optional name of a function to perform easing of the animation. Easing functions must be registered by name and are often provided by plugins. Core jQuery supplies two easing functions registered as linear and swing.

callback

(Function) An optional function invoked when the animation completes. No parameters are passed to this function, but the function context (this) is set to the element that was animated.

options

(Object) Specifies the animation parameter values using an object hash. The supported properties are as follow:

  • duration—See previous description of duration parameter.
  • easing—See previous description of easing parameter.
  • complete—Function invoked when the animation completes.
  • queue—If false, the animation isn’t queued and begins running immediately.

Returns

The wrapped set.


We create custom animations by supplying a set of CSS style properties and target values that those properties will converge towards as the animation progresses. Animations start with an element’s original style value and proceed by adjusting that style value in the direction of the target value. The intermediate values that the style achieves during the effect (automatically handled by the animation engine) are determined by the duration of the animation and the easing function.

The specified target values can be absolute values, or we can specify relative values from the starting point. To specify relative values, prefix the value with += or -= to indicate relative target values in the positive or negative direction, respectively.

The term easing is used to describe the manner in which the processing and pace of the frames of the animation are handled. By using some fancy math on the duration of the animation and current time position, some interesting variations to the effects are possible. The subject of writing easing functions is a complex, niche topic that’s usually only of interest to the most hard-core of plugin authors; we’re not going to delve into the subject of custom easing functions in this book. If you’d like to sample more easing functions than linear (which provides a linear progression) or swing (which speeds up slightly near the end of an animation), check out the Easing Plugin at http://gsgd.co.uk/sandbox/jquery.easing.php.

By default, animations are added to a queue for execution; applying multiple animations to an object will cause them to run serially. If you’d like to run animations in parallel, set the queue option to false.

The list of CSS style properties that can be animated is limited to those that accept numeric values for which there is a logical progression from a start value to a target value. This numeric restriction is completely understandable—how would we envision the logical progress from a source value to an end value for a non-numeric property such as image-background? For values that represent dimensions, jQuery assumes the default unit of pixels, but we can also specify em units or percentages by including the em or % suffixes.

Frequently animated style properties include top, left, width, height, and opacity. But if it makes sense for the effect we want to achieve, numeric style properties such as font size and border widths can also be animated.


Note

If you want to animate a CSS value that specifies a color, you may be interested in the official jQuery Color Animation Plugin at http://jquery.com/plugins/project/color.


In addition to specific values, we can also specify one of the strings hide, show, or toggle; jQuery will compute the end value as appropriate to the specification of the string. Using hide for the opacity property, for example, will result in the opacity of an element being reduced to 0. Using any of these special strings has the added effect of automatically revealing or removing the element from the display (like the hide() and show() commands).

Did you notice when we introduced the core animations that there was no toggling command for the fade effects? That’s easily solved using animate() and toggle as follows:

$('.animateMe').animate({opacity:'toggle'},'slow'),

Let’s try our hand at writing a few more custom animations.

5.3.1. A custom scale animation

Consider a simple scale animation in which we want to adjust the size of the elements to twice their original dimensions. We write such an animation as

$('.animateMe').each(function(){
$(this).animate(
{
width: $(this).width() * 2,
height: $(this).height() * 2
},
2000
);
});

To implement this animation, we iterate over all the elements in the wrapped set via each() to apply the animation individually to each matched element. This is important because the property values that we need to specify for each element are based upon the individual dimensions for that element. If we always knew that we’d be animating a single element (such as if we were using an id selector) or applying the exact same set of values to each element, we could dispense with each() and animate the wrapped set directly.

Within the iterator function, the animate() command is applied to the element (identified via this) with style property values for width and height set to double the element’s original dimensions. The result is that over the course of two seconds (as specified by the duration parameter of 2000), the wrapped elements (or element) will grow from their original size to twice that original size.

Now let’s try something a bit more extravagant.

5.3.2. A custom drop animation

Let’s say that we want to conspicuously animate the removal of an element from the display, perhaps because it’s vitally important to convey to users that the item being removed is gone and that they should make no mistake about it. The animation we’ll use to accomplish this will make it appear as if the element drops off the page, disappearing from the display as it does so.

If we think about it for a moment, we can figure out that, by adjusting the top position of the element, we can make it move down the page to simulate the drop; adjusting the opacity will make it seem to vanish as it does so. And finally, when all that’s done, we want to remove the element from the display (similar to the animated hide()).

We accomplish this drop effect with the following code:

$('.animateMe').each(function(){
$(this)
.css('position','relative')
.animate(
{
opacity: 0,
top: $(window).height() - $(this).height() -
$(this).position().top
},
'slow',
function(){ $(this).hide(); });
});

There’s a bit more going on here than with the previous effect. We once again iterate over the element set, this time adjusting the position and opacity of the elements. But to adjust the top value of an element relative to its original position, we first need to change its CSS position style property value to relative.

Then for the animation, we specify a target opacity of 0 and a computed top value. We don’t want to move an element so far down the page that it moves below the window’s bottom; this could cause scroll bars to be displayed where none may have been before, possibly distracting users. We don’t want to draw their attention away from the animation—grabbing their attention is why we’re animating in the first place! So we use the height and vertical position of the element, as well as the height of the window, to compute how far down the page the element should drop.


Note

In most examples in this book, we’ve avoided using plugins as much as possible in order to focus on core jQuery. This doesn’t always reflect real-world situations where core jQuery is usually used along with whatever plugins a page author needs to get the job done. The ease of writing jQuery plugins and the rich pool of plugins that are available are two of jQuery’s greatest strengths. In this example animation (as well as the next that we’ll examine), we’ve employed the services of the Dimensions Plugin’s position() command to determine the initial location of the element relative to the page. We’ll be looking into the Dimensions Plugin in more detail in chapter 9 (section 9.2, to be exact).


When the animation is complete, we want to remove the element from the display, so we specify a callback routine that applies the non-animated hide() command to the element (which is available to the function as its function context).


Note

We did a little more work than we needed to in this animation, so we could demonstrate doing something that needs to wait until the animation is complete in the callback function. If we were to specify the value of the opacity property as hide rather than 0, the removal of the element(s) at the end of the animation would be automatic, and we could dispense with the callback.


Now let’s try one more type of “make it go away” effect for good measure.

5.3.3. A custom puff animation

Rather than dropping elements off the page, let’s say that we want an effect that makes it appear as if the element dissipates away into thin air like a puff of smoke. To animate such an effect, we combine a scale effect with an opacity effect, growing the element while fading it away. One issue we need to deal with for this effect is that this dissipation would not fool the eye if we let the element grow in place with its upper-left corner anchored. We want the center of the element to stay in the same place as it grows, so we need to adjust the position of the element, in addition to its size, as part of the animation.

The code for our puff effect is

$('.animateMe').each(function(){
var position = $(this).position();
$(this)
.css({position:'absolute',top:position.top,
left:position.left})
.animate(
{
opacity: 'hide',
width: $(this).width() * 5,
height: $(this).height() * 5,
top: position.top - ($(this).height() * 5 / 2),
left: position.left - ($(this).width() * 5 / 2)
},
'normal'),
});

In this animation, we decrease the opacity to 0 while growing the element to five times its original size and adjusting its position by half that new size, resulting in the position of the center of the element remaining constant. We don’t want the elements surrounding the animated element to be pushed out while the target element is growing, so we take it out of the flow by changing its position to absolute and explicitly setting its position coordinates.

Because we specify hide for the opacity value, the elements are automatically hidden (removed from the display) once the animation is complete.

Each of these three custom effects can be observed by loading the page at chapter5/custom.effects.html whose display is shown in figure 5.5.

Figure 5.5. Initial display of the page that demonstrates the three custom effects: scale, drop, and puff

We purposefully kept the browser window to a minimum for the screen shot; you’ll want to make the window bigger when running this page to properly observe the behavior of the effects. And although we’d love to show you how these effects behave, screenshots have obvious limitations. Nevertheless, figure 5.6 shows the puff effect in progress.

Figure 5.6. The puff effect expands and moves the image while simultaneously reducing its opacity.

We’ll leave it to you to try out the various effects on this page and observe their behavior.

5.4. Summary

This chapter introduced us to the animated effects that jQuery makes available out-of-the-box, as well as to the animate() wrapper method that allows us to create our own custom animations.

The show() and hide() commands, when used without parameters, reveal and conceal elements from the display immediately, without any animation. We can perform animated versions of the hiding and showing of elements with these commands by passing parameters that control the speed of the animation, as well as providing an optional callback that’s invoked when the animation completes. The toggle() command toggles the displayed state of an element between hidden and shown.

Another set of wrapper methods, fadeOut() and fadeIn(), also hides and shows elements by adjusting the opacity of elements when removing or revealing them in the display. A third method, fadeTo(), animates a change in opacity for its wrapped elements without removing the elements from the display.

A final set of three built-in effects animates the removal or display of our wrapped elements by adjusting their vertical height: slideUp(), slideDown(), and slideToggle().

For building our own custom animations, jQuery provides the animate() command. Using this method, we can animate any CSS style property that accepts a numeric value, most commonly the opacity and dimensions of the elements. We explored writing some custom animations that remove elements from the page in novel fashions.

We wrote the code for these custom effects as inline code within the on-page JavaScript. A much more common, and useful, method is to package these custom animations as jQuery commands. We’ll learn how to do that in chapter 7, and you’re encouraged to revisit these effects after you’ve read that chapter. Repackaging the custom effects found in this chapter, and any that you can think up on your own, would be an excellent follow-up exercise.

But before we write our own jQuery extensions, let’s take a look at some high-level functions that jQuery provides.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.23.86.219