Animating jQuery (Javascript And Ajax)

In This Chapter

Setting up for animation
Hiding and showing elements with jQuery
Fading elements in and out
Adding a callback function to a transition
Understanding object chaining
Modifying elements
Using selection filters
The jQuery library simplifies a lot of JavaScript coding. One of its biggest advantages is how it allows you to add features that would be difficult to achieve in ordinary JavaScript and DOM (document object model) programming. This chapter teaches you to shake and bake your programs by identifying specific objects; moving them around; and making them appear, slide, and fade.

Getting Prepared for Animation

To get your jQuery animation career started, take a look at hideShow.html, shown in Figure 11-1.
The hideShow program looks simple at first, but it does some very interesting things. All of the level-two headings are actually buttons, so when you click them, fun stuff happens:
The Show button displays a previously hidden element. Figure 11-2 demonstrates the new content.
The Hide button hides the content. The behavior of the hide button is pretty obvious. If the content is showing, clicking the button makes it disappear instantly.
The Toggle button swaps the visibility of the content. If the content is currently visible, clicking the button hides it. If it is hidden, a click of the button makes it show up.
At first, the page shows nothing much.
Figure 11-1:
At first, the page shows nothing much.
‘ The Slide Down button makes the content transition in. The slide down transition acts like a window shade being pulled down to make the content visible through a basic animation.
The Slide Up button transitions the content out. This animation looks like a window shade being pulled up to hide the content.
The Fade In button allows the element to dissolve into visibility. This animation looks much like a fade effect used in video. As in the sliding animations, you can control the speed of the animation.
A special function is called when the fade in is complete. In this example, I call a function named present as soon as the fade in is complete. This is a callback function, which I explain in just a bit.
The Fade Out button fades the element to the background color. This technique gradually modifies the opacity of the element so it gradually disappears.

Here are a couple of details for you to keep in mind:

You can adjust how quickly the transition animation plays. For example,
the hideShow program plays the slide down at a slow speed, and slide up faster. You can even specify exactly how long the transition takes in milliseconds (1/1000ths of a second).
‘ Any transition can have a callback function attached. A callback function is a function that will be triggered when the transition is complete.
Of course, the showHide example relies on animation, which isn’t easy to see in a static topic. Please be sure to look at this and all other example  Better yet, install them on your own machine and play around with my code until they make sense to you.
The content element is now visible.
Figure 11-2:
The content element is now visible.
The animations shown in this example are useful when you want to selectively hide and display parts of your page. Being able to show and hide elements is useful in a number of situations. Menus are one obvious use. You might choose to store your menu structure as a series of nested lists, displaying parts of the menu only when the parent is activated. Another common use of this technology is to have small teaser sentences that expand to show more information when the user clicks or hovers the mouse pointer over them. This technique is commonly used on blog and news sites to let users preview a large number of topics, kind of like a text-based thumbnail image.
The jQuery library has built-in support for transitions that make these effects pretty easy to produce. Look over the entire hideShow.html program before digging in on the details.
tmp13639_thumb_thumbtmp13640_thumb_thumbtmp13641_thumb_thumb
This example might look long and complicated when you view it all at once, but it isn’t hard to understand when you break it into pieces. The following sections help you get comfortable with this example.

Writing the HTML and CSS foundation

The HTML used in this example is minimal, as is common in jQuery development. It consists of a single level-one heading, a series of level-two headings, and a paragraph. The level-two headings will be used as buttons in this example. I use a CSS style to make the <h2> tags look more like buttons (adding a border and background color). I added an id attribute to every button so I can add jQuery events later.
If I wanted the h2 elements to look and act like buttons, why didn’t I just make them with button tags in the first place? That’s a very good question. At one level, I probably should use the semantically clear button tag to make a button. However, in this example, I want to focus on the jQuery and keep the HTML as simple as possible. jQuery can help you make any element act like a button, so that’s what I did. Users don’t expect h2 elements to be clickable, so you need to do some styling (as I did) to help the users understand that they can click the element. For comparison purposes, the other two examples in this chapter use actual HTML buttons.
The other interesting part of the HTML is the content div. In this example, the actual content isn’t really important, but I did add some CSS to make the content very easy to see when it pops up. The most critical part of the HTML from a programming perspective is the inclusion of the id attribute. This attribute makes it easy for a jQuery script to manipulate the component so that it hides and reappears in various ways. Note that the HTML and CSS does nothing to hide the content. It will be hidden (and revealed) entirely through jQuery code.

Initializing the page

The initialization sequence simply sets the stage and assigns a series of event handlers:

tmp13642_thumb_thumb

The pattern for working with jQuery should now be familiar:

1. Set up an initialization function.
Use the $(document).ready() mechanism described in Chapter 12 or this cleaner shortcut to specify an initialization function.
2. Hide the content div.
When the user first encounters the page, the content div should be hidden.
3. Attach event handlers to each h2 button.
This program is a series of small functions. The init() function attaches each function to the corresponding button. Note how I carefully named the functions and buttons to make all the connections easy to understand.

Working with callback functions

As you look through the JavaScript and jQuery code in hideShow.html, you’ll probably spot a pattern. The init() function adds event handlers to several of the elements on the page. These event handlers specify the names of various functions. The rest of the JavaScript code is simply the definitions of these functions.
This technique is heavily used in jQuery programming. When you define an event, you will often specify a function that should be called when that event is triggered. Such a function is often referred to as a callback function.
In this context, the function name is treated as a variable, so it doesn’t need the parentheses you normally use when referring to functions.

Hiding and Showing the Content

All the effects on the page shown earlier in Figure 11-1 are based on hiding and showing the content div. The hide() and show() methods illustrate how jQuery animation works.
tmp13643_thumb_thumb

Each of these functions works in the same basic manner:

1. Identify the content div.
Create a jQuery node based on the content div. If you need more information on creating jQuery node objects, please check Chapter 10.
2. Hide or show the node.
The jQuery object has built-in methods for hiding and showing.
The hide() and show() methods act instantly. If the element is currently visible, the show() method has no effect. Likewise, hide() has no effect on an element that’s already hidden.
The following sections describe some fun tricks for revealing or concealing elements.

Toggling visibility

In addition to hide() and show(), the jQuery object supports a toggle() method. This method takes a look at the current status of the element and changes it. If the element is currently hidden, clicking the button makes it visible. If it’s currently visible, clicking the button hides it. The toggle Content() function illustrates how to use this method:
tmp13644_thumb_thumb

Sliding an element

jQuery supports a window blind effect that allows you to animate the appearance and disappearance of your element. The general approach is very similar to hide() and show() , but the effect has one additional twist:
tmp13645_thumb_thumb
The slideDown() method makes an element appear like a window shade being pulled down. The slideUp() method makes an element disappear in a similar manner. These functions take a speed parameter that indicates how quickly the animation occurs. The speed can be a string value (“fast”, “medium”, or “slow”) or a numeric value in milliseconds (measured in 1,000th of a second). The value 50 0 means 500 milliseconds, or half a second. If you leave out the speed parameter, the default value is “medium”.
The show(), hide(), and toggle() methods also accept a speed parameter. In these functions, the object shrinks and grows at the indicated speed.
There is also a slideToggle() function available that toggles the visibility of the element, but using the sliding animation technique.

Fading an element in and out

Another type of animation is provided by the fade methods. These techniques adjust the opacity of the element. The code should look quite familiar by now:
tmp13646_thumb_thumb
fadeIn() and fadeout() work just like the hide() and slide() techniques. The fading techniques adjust the opacity of the element and then remove it, rather than dynamically changing the size of the element as the slide and show techniques do.
I’ve added one more element to the fadeIn() function. If you supply the fadeIn() method (or indeed any of the animation methods described in this section) with a function name as a second parameter, that function is a callback function, meaning it is called upon completion of the animation. When you click the fade in button, the content div slowly fades in, and then when it is completely visible, the present() function gets called. This function doesn’t do a lot in this example — it simply pops up an alert — but it could be used to handle some sort of instructions after the element is visible.
If the element is already visible, the callback method will be triggered immediately.

Changing an Element’s Position With jQuery

The jQuery library also has interesting features for changing any of an element’s characteristics, including its position. The animate.html page featured in Figure 11-3 illustrates a number of interesting animation techniques.
You know what I’m going to say, right? This program moves things around. You can’t see that in a topic. Be sure to look at the actual page. Trust me; it’s a lot more fun than it looks in this screen shot.
Click the buttons, and the element moves. (I added the arrow to indicate motion.)
Figure 11-3:
Click the buttons, and the element moves. (I added the arrow to indicate motion.)
This page (animate.html) illustrates how to move a jQuery element by modifying its CSS. (Check Bonus Chapter 2 on the Web site if you’re unfamiliar with CSS.) It also illustrates an important jQuery technique called object chaining as well as a very useful animation method that allows you to create smooth motion over time. Look over the entire code first, and then in the following sections I break it into sections for more careful review:
tmp13648_thumb_thumbtmp13649_thumb_thumbtmp13650_thumb_thumb

Creating the HTML framework

The HTML always forms the foundation of a JavaScript program. The animate. html page is similar to the hideShow page (shown earlier in the chapter), but I decided to use a real form with buttons as the control panel. Buttons aren’t difficult to use, but they’re a little more tedious to code because they must be inside a form element as well as a block-level element, and they require more coding to produce than h2 elements.
Note that I use &lt; in one of the button captions. (You can find it near the end of the animate.html listing.) This HTML attribute displays the less-than symbol. Had I used the actual symbol (<) the browser would have thought I was beginning a new HTML tag and would have been confused.
The buttons all have id attributes, but I didn’t attach functions to them with the onclick attribute. When you’re using jQuery, it makes sense to commit to a jQuery approach and use the jQuery event techniques.
The only other important HTML element is the content div. Once again, this element is simply a placeholder, but I added CSS styling to make it obvious when it moves around. It’s important that you set this element to be absolutely positioned, because the position will be changed dynamically in the code.

Setting up the events

The initialization is all about setting up the event handlers for the various buttons. Begin with an init() function called when the document is ready. That function contains callback functions (such as move and glide) for the various events, directing traffic to the right functions when a user presses a button:
tmp13651_thumb_thumb
As usual, naming conventions make it easy to see what’s going on.

Don’t go chaining

jQuery supports a really neat feature called node chaining that allows you to put several steps into one single line. This makes your code a lot easier to write, and it allows you to do several things to a particular element or group of elements at once. As an example, take another look at the move() function defined in animate.html.
The move function isn’t really that radical. All it really does is use the css() method described in Chapter 10 to alter the position of the element. After all, position is just a CSS attribute, right? Well, it’s a little more complex than that. The position of an element is actually stored in two attributes, top and left. Your first attempt at a move function would probably look like this:
tmp13652_thumb_thumb
Although this approach certainly works, it has a subtle problem. It moves the element in two separate steps. Although most browsers are fast enough to prevent this from being an issue, node chaining allows you to combine many jQuery steps into a single line.
Almost all jQuery methods return a jQuery object as a side effect. So, the line
tmp13653_thumb_thumb
not only changes the text of the content node, but actually makes a new node. You can attach that node to a variable like this if you want:
tmp13654_thumb_thumb
However, what most jQuery programmers do is simply attach new functionality onto the end of the previously defined node, like this:
tmp13655_thumb_thumb
This new line takes the node created by $(“#content”) and changes its text value. It then takes this new node (the one with changed text) and adds a click event to it, calling the hiThere() function when the content element is clicked. In this way, you build an ever-more complex node by chaining nodes on top of each other.
These node chains can be hard to read because they can result in a lot of code on one physical line. JavaScript doesn’t really care about carriage returns, though, because it uses the semicolon to determine the end of a logical line. You can change the complex chained line so it fits on several lines of the text editor like this:
tmp13656_thumb_thumb
Note that only the last line has a semicolon because what’s shown is all one line of logic even though it occurs on three lines in the editor.

Building the move() function with chaining

Object chaining makes it easy to build the move function so that it moves the content’s left and top properties simultaneously:
tmp13657_thumb_thumb
This function uses the css() method to change the left property to 50px. The resulting object is given a second css() method call to change the top property to 10 0px. The top and left elements are changed at the same time as far as the user is concerned.

Building time-based animation with animate()

Using the css() method is a great way to move an element around on the screen, but the motion is instantaneous. jQuery supports a powerful method called animate(), which allows you to change any DOM characteristics over a specified span of time. The glide button on animate.html smoothly moves the content div from (50, 100) to (400, 200) over two seconds.
tmp13658_thumb_thumb
The function begins by moving the element immediately to its initial spot with chained css() methods. It then uses the animate() method to control the animation. This method can have up to three parameters:
A JSON object describing attributes to animate: The first parameter is an object in JSON notation describing name/value attribute pairs. In this example, I’m telling jQuery to change the left attribute from its current value to 400px and the top value to 200px. Any numeric value that you can change through the DOM can be included in this JSON object. Instead of a numerical value, you can use “hide”, “show”, or “toggle” to specify an action. Review Chapter 5 for more on JSON objects if you’re unfamiliar with them.
A speed attribute: The speed parameter is defined in the same way as the speed for fade and slide animations. There are three predefined speeds: “slow”, “medium”, and “fast”; speed can also be indicated in milliseconds (so 2000 means 2 seconds).
A callback function: This optional parameter describes a function to be called when the animation is complete. I describe the use of callback functions earlier in this chapter in the section called “Fading an element in and out.”

Move a little bit: Relative motion

You can use the animation mechanism to move an object relative to its current position. The arrow buttons and their associated functions perform this task:
tmp13659_thumb_thumb
These functions also use the animate() method, but there’s a small difference in the position parameters. The += and -= modifiers indicate that I want to add to or subtract from the value rather than indicating an absolute position. Of course, you can add as many parameters to the JSON object as you want, but these are a good start.
Note that since I’m moving a small amount (ten pixels) I want the motion to be relatively quick. Each motion lasts 100 milliseconds.
The jQuery animation() method supports one more option: easing. The term easing refers to the relative speed of the animation throughout its lifespan. If you watch the animations on the animate.html page carefully, you’ll see that the motion begins slowly, builds up speed, and slows down again at the end. This provides a natural-feeling animation. By default, jQuery animations use what’s called a swing easing style (slow on the ends, fast in the middle, like a child on a swing). If you want to have a more consistent speed, you can specify “linear” as the fourth parameter, and the animation will work at a constant speed. You can also install plugins for more advanced easing techniques.

Modifying Elements on the Fly

The jQuery library supports a third major way of modifying the page: the ability to add and remove contents dynamically. This is a powerful way to work with a page. The key to this feature is another of jQuery’s most capable tools: its flexible selection engine. You’ve already seen how you can select jQuery nodes using the standard CSS-style selectors, but you can also use numerous attributes to modify nodes. The changeContent.html page demonstrates some of the power of these tools (see Figure 11-4).
Of course, the buttons allow the user to make changes to the page dynamically. Pressing the Add Text button adds more text to the content area, as you can see in Figure 11-5.
The default state of change-Content is a little dull.
Figure 11-4:
The default state of change-Content is a little dull.
More text can be appended inside any content area.
Figure 11-5:
More text can be appended inside any content area.
The Clone button is interesting because it allows you to make a copy of an element and place it somewhere else in the document hierarchy. Pressing the Clone button a few times can give you a page like Figure 11-6.
It’s possible to wrap an HTML element around any existing element. The Wrap in Div button puts a div (with a red border) around every cloned element. You can press this multiple times to add multiple wrappings to any element. Figure 11-7 shows what happens after I wrap a few times.
For readability, sometimes you want to be able to alternate styles of lists and tables. jQuery offers an easy way to select every other element in a group and give it a style. The Change Alternate Paragraphs button activates some code that turns all odd-numbered paragraphs into white text with a green background. Look at Figure 11-8 for a demonstration.
Finally, the Reset button demonstrates how you can reset all the changes you made with the other buttons.
I've made several clones of the original content.
Figure 11-6:
I’ve made several clones of the original content.
Now there's a red-bordered div around all the cloned elements.
Figure 11-7:
Now there’s a red-bordered div around all the cloned elements.
All odd-numbered paragraphs have a new style.
Figure 11-8:
All odd-numbered paragraphs have a new style.
The code for changeContent.html seems complex, but it follows the same general patterns in jQuery programming that I show you earlier in this chapter. As always, look over the entire code first, and then I break it down.
tmp1633_thumb_thumbtmp1634_thumb_thumbtmp1635_thumb_thumb
I admit, this program has a lot of code, but when you consider how much functionality this page has, it really isn’t too bad. Look at it in smaller pieces, and it all make sense.
Building the basic page
As usual, begin by inspecting the HTML. The basic code for this page sets up the playground.
1. Create a form with buttons.
This form becomes the control panel. Add a button for each function you want to add. Make sure each button has an ID, but you don’t need to specify an onclick function, because the init() function will take care of that.
2. Build a prototype content div.
Build a div called content, and add a paragraph to the div.
It’s very important to be careful with your initial HTML structure. The manipulation and selection tricks that you experiment with in this chapter rely on a thorough understanding of the beginning page structure. Be sure you understand exactly how the page is set up so that you’ll understand how to manipulate it. If your standard XHTML page (before any JavaScript/jQuery code is added) doesn’t validate, it’s unlikely your code will work as expected.

Initializing the code

The initialization section is pretty straightforward. Set up an init() function and use it to assign event handlers to all the buttons:
tmp1636_thumb_thumb

Adding text

Adding text to a component is pretty easy. The append() method attaches text to the end of a jQuery node. Table 11-1 shows a number of other methods for adding text to a node.

Table 11-1 Adding Content to jQuery Nodes
Method Description
append(text) Adds the text (or HTML) to the end of the
selected element(s).
prepend(text) Adds the content at the beginning of the
selected element(s).
insertAfter(text) Adds the text after the selected element
(outside the element).
insertBefore(text) Adds the text before the selected element
(outside the element).

More methods are available, but these are the ones I find most useful. Be sure to check out the official documentation at http://docs.jquery.com to see the other options.
tmp1637_thumb_thumb
The append() method adds the new text to the end of the text already inside the element, so it becomes part of the paragraph contained inside the content div. For example, if you have this element: <div>one</div> and you append two to the div, you’ll get <div>onetwo</div>, not <div>one</ div>two.

The more interesting part of this code is the selector. It could read like this:

tmp1638_thumb_thumb
That would add the text to the end of the paragraph. The default text has only one paragraph, so that makes lots of sense. If there are more paragraphs (and there will be), the p selector will select them all, adding the text to all the paragraphs simultaneously. By specifying p:first, I’m using a special filter to determine exactly which paragraph should be affected. Many of the examples on this page use jQuery filters, so I describe them elsewhere in this section. For now, note that p:first means the first paragraph. Of course, there are also p:last and many more. Read on. . . .

Attack of the clones

You can clone (copy) anything you can identify as a jQuery node. This cloning makes a copy of the node without changing the original. The cloned node isn’t immediately visible on the screen. You need to place it somewhere, usually with an append(),prepend(), insertBefore(), or insertAfter() method.

Take a look at the clone() function to see how it works:

tmp1639_thumb_thumb
1. Select the first paragraph.
The first paragraph is the one I want to copy. (In the beginning, there’s only one, but that will change soon.)
2. Use the clone() method to make a copy.
Even though this step makes a copy, it still isn’t visible. Use chaining to do some interesting things to this copy. (I explain chaining earlier in the chapter, in the section “Don’t go chaining . . .”)
3. Add the new element to the page after the last paragraph.
The p:last identifier is the last paragraph, so insertAfter (“p:last”) means put the new paragraph after the last paragraph available in the document.
4. Change the CSS.
Just for grins, chain the css() method onto the new element and change the background color to light blue. This just reinforces that you can continue adding commands to a node through chaining.
Note that the paragraphs are still inside the content div. Of course, I could have put them elsewhere with careful use of selectors, but that’s where I want them.
Keeping track of changes to the page is difficult because a standard View Source command shows you the original source code, not the code that’s been changed by your jQuery magic. jQuery changes the HTML of your page in memory, but doesn’t change the text file that contains your page. If your page isn’t doing what you expect, you need to look at the script-generated source code to see what’s really going on. Firefox plugins are the key to headache-free debugging. The Web developer toolbar has a wonderful feature called View Generated Source (available under the View Source menu), which shows the page source as it currently exists in memory. If you prefer the Firebug extension, its inspect mode also inspects the page as it currently is displayed. Both tools are described in Chapter 1.
Note that the content of the first paragraph is cloned with its current content and style information copied to the new element. If you clone the paragraph and then add content to it and clone it again, the first clone has the default text, and the second clone contains the additional text. If you modify the CSS of an element and then clone it, the clone also inherits any of the style characteristics of the original node.

It’s a Wrap

Sometimes you want to embed an object inside another element (or two). For example, the wrap button on the changeContent page surrounds each cloned paragraph with a <div></div> pair. I’ve defined the <div>tag in my CSS to include a red border. Repeatedly clicking the Wrap button surrounds all cloned paragraphs with red borders. This would be a very tedious effect to achieve in ordinary DOM and JavaScript, but jQuery makes it pretty easy to do.
tmp16310_thumb_thumb
The wrap method is pretty easy to understand. If you feed it any container tag, it wraps that container around the selected node. You can also use multiple elements, so if you want to enclose a paragraph into a single item list, you can do something like this:
tmp16311_thumb_thumb
The resulting code would surround each paragraph with an unordered list and list item.
Returning to the wrap function, I’ve decided not to wrap every paragraph with a div, just the ones that have been cloned. (Mainly I’m doing this so I can show you some other cool selection filters.) The selector p:gt(0) means “select all paragraphs with an index greater than zero.” In other words, ignore the first paragraph but apply the following methods to all other paragraphs. There is also a less-than filter (:lt), which isolates elements before a certain index, and an equals filter (:eq), which isolates an element with a certain index.

Alternating styles

People commonly alternate background colors on long lists or tables of data, but this can be a tedious effect to achieve in ordinary CSS and JavaScript. Not surprisingly, jQuery selectors make this a pretty easy job:
tmp16312_thumb_thumb
The :odd selector only chooses elements with an odd index and returns a jQuery node that can be further manipulated with chaining. Of course, you can use an :even selector for handling the even-numbered nodes. The rest of this code is simply CSS styling.

Resetting the page

If you can do all this modification to the page, you’ll also need to be able to restore it to its pristine state. A quick jQuery function can easily do the trick:
tmp16313_thumb_thumb
This function reviews many of the jQuery and selection tricks shown in this chapter.
1. Remove all but the first paragraph.
Any paragraphs with an index greater than zero is a clone, so it needs to go away. The remove() method removes all jQuery nodes associated with the current selector.
2. Remove all divs but the original content.
I could have used the :gt selector again, but instead I use another interesting selector: :not. This selector means “remove every div that isn’t the primary content div.” Using this selector removes all divs added through the wrap function.
3. Reset the original content div to its default text.
Set the default text back to its original status so the page is reset.
Truthfully, all I really need here is the last line of code. Changing the HTML of the content div replaces the current contents with whatever is included, so the first two lines aren’t entirely necessary in this particular context. Still, it’s very useful to know how to remove elements when you need to do so.

More fun With selectors and filters

The jQuery selectors and filters are really fun and powerful. Table 11-2 describes a few more filters and how you can use them.

Table 11-2 Common jQuery Filters
Filter Description
:header Any header tag (h1, h2, h3).
:animated Any element that is currently being animated.
:contains(text) Any element that contains the indicated text.
:empty The element is empty.
:parent This element contains some other element.
:attribute=value The element has an attribute with the specified
value.
:Input, :text, Matches on the specific element type (especially
:radio, :image, useful for form elements that are all variations of the
:button, and so on input tag).

Note that this is a representative list. Be sure to check out the official documentation at http://docs.jquery.com for a more complete list of filters.

Next post:

Previous post: