You are on page 1of 15

Ch3 - Animating, Scrolling, and Resizing

*Contents
.animate
.hide

*Easing (Linear Swing)


.show

*Animation Queue
.slideDown

*Chaining Actions
.fadeOut

.delay

.hover (= 2 Func M/Over & M/Out)


.stop .effect(Effect UI Library)
.scroll (Event)

.scrollTo

.append

*return false

.jScrollPane
.resize (Event)

.width

.remove

.resizable (Plug-in)

Animating
Animating CSS Properties
$('p').animate({
padding: '20px',
borderBottom: '3px solid #8f8f8f',
borderRight: '3px solid #bfbfbf'
}, 2000);
Animate Parameters - Has to be

= Key/Value Pairs

= camelCase
*The values you define can be relative to the elements current
values: all you need to do is specify += or -= in front of the
value, and that value will be added to or subtracted from the
elements current property.
$('p').animate({
padding: '20px',

borderBottom: '3px solid #8f8f8f',


borderRight: '3px solid #bfbfbf'
}, 2000);
Adds a Padding (All Around) & Borders over a 2sec Interval
$('#navigation li').hover(function() {
$(this).animate({paddingLeft: '+=15px'}, 200);
}, function() {
$(this).animate({paddingLeft: '-=15px'}, 200);
});
= Must be NO Space between += & Value
- 1st Function on Hover-over
- 2nd Function on Hover-out
You can also use animate to achieve fine-grained control over
the showing, hiding, and toggling functions we saw in Chapter
2. We simply specify a propertys animation value as show,
hide, or toggle rather than a numeric amount:
=>
$('#disclaimer').animate({
opacity: 'hide',
height: 'hide'
}, 'slow');

Color Animation
Unlike a height or width value that moves from one value to another in a simple,
linear manner, jQuery needs to do some extra math to figure out what color is,
say, three-quarters of the way between light blue and orange.
This color-calculating functionality is omitted from the core library. This makes
sense when you think about it: most projects have no need for this functionality,
so jQuery can keep the size of the core library to a minimum. If you want to
animate color, youre going to need to download the Color Animations plugin.1

Easing

linear and swing

Easing refers to the acceleration and deceleration that occurs


during an animation to give it a more natural feel.
swing easing = starts off slowly before gaining speed, then
towards the end of the animation it slows down again, nice and
gently. Visually, swing easing looks far more natural than linear
easing, and jQuery uses it by default (if no easing parameter is
specified).

$('p:first').toggle(function() {
$(this).animate({'height':'+=150px'}, 1000, 'linear');
}, function() {
$(this).animate({'height':'-=150px'}, 1000, 'swing');
});

Advanced Easing

There is a vast array of easing options beyond these two basic


types included in the core jQuery library. Most of these are
available in the easing plugin, available from the jQuery plugin
repository.

jQuery UI Includes Several Plugins

By including the jQuery UI library, youll avoid needing to


include each plugin separately in your pages.
The easing plugin simply gives you access to over 30 new
easing options.
*Easing Plugin Library (= included in Effects in JQ UI Library)
egs:
$('p:first').animate({height: '+=300px'}, 2000,
'easeOutBounce');$('p:first').animate({height: '-=300px'}, 2000,
'easeInOutExpo');$('p:first').animate({height: 'hide'}, 2000,
'easeOutCirc');$('p:first').animate({height: 'show'}, 2000,
'easeOutElastic');
The best way to see all the available equations is to view the
plugins source code.
Jumpy Animation?
One quirk to be aware of is that animating an element directly next to a heading tag
can sometimes look jumpyespecially when the element hides. This is due to the
headings margin, which collapses as the following element hides. A simple
workaround, which weve used here, is to remove margins from the heading tag
entirely.

*Ex = (Kind of Like) Accordion


<div id="bio">
<h2>Whos Hot Right Now?</h2>

= Wrapper 4 Accordion Content

<h3>Beau Dandy</h3>
= Click Event Tied to <h3>s
<div>
<img src="../../images/beau_100.jpg" width="100" height="100 "/>
<p>Content about Beau Dandy</p>
</div>
<h3>Johny Startdust</h3>
<div>
<img src="../../images/johnny_100.jpg" width="100" height="100 "/>
<p>After smashing into </p>
</div>

<h3>Glendatronix</h3>
<div>
<img src="../../images/glenda_100.jpg" width="100" height="100 "/>
<p>Content about Glendatronix</p>
</div>
</div><!--end #bio-->
$(function() {
$('#bio > div').hide();
//Hide any <div>s that are Children of #bio
$('#bio > div:first').show();
//Contents Visible of 1st <div> in #bio
$('#bio h3').click(function() { //Click <h3> & then its Next Sibling
$(this).next().animate(
= a <div> w/ <img> & <p> - becomes Visible
{ height: 'toggle'}, 'slow', 'easeOutBounce' by Toggling its Height
);
});
});

The Animation Queue


animate(parameters, options);

Options = duration, easing, and complete(the callback


method) step and queue
$('p:first').animate(
{ height: '+=100px', backgroundColor: 'green'
},
{ duration: 'slow', easing: 'swing', complete: function() {alert('done!');},
queue: false
}
);

You can accomplish almost all of this with the simpler format
that weve already seen. You only need the advanced version
if you want to specify additional settings, like the queue
parameter.
The queue is the list of animations waiting to occur on a
particular element. Every time we ask jQuery to perform an
animation on an element, that animation is added to the
queue. The element executes the queue one at a time until
everything is complete

Chaining Actions
Chaining links two or more jQuery actions into a single statement.
- eg.

$('p:first').hide().slideDown('slow').fadeOut();

Its often good to lay out your actions on separate lines for
clarity
$('p:first')
.hide()
.slideDown('slow')
.fadeOut();

Pausing the Chain

.delay()

This can be a great way to control your animations more precisely.

$('p:first')
.hide()
.slideDown('slow')
.delay(2000)
.fadeOut();

= Pauses for 2sec (b4 Fading out)

Animated Navigation
1. Ex = Nav Hover (Wobbling) Blob
lets apply our newly discovered jQuery power to create a Flash-like
navigation bar. It will have a background blob that wobbles around to
highlight the menu choice the user is hovering over.
Our background color blob will be an empty div element, positioned behind
whichever navigation link the user is mousing over.
1. Our first task, therefore, will be to create the element and append it to the
document:

$('<div id="navigation_blob"></div>').css({
width: $('#navigation li:first a').width() + 10,
height: $('#navigation li:first a').height() + 10
}).appendTo('#navigation').hide(); = Hidden until Hover
2. = 2nd Task => Hover Event
-

In this Step, we use a jQuery method called position. This is


an action that does nothing on its own, but when called
exposes two properties: left and top; these are the left
and top offsets of the selected element relative to its
parent.

We set the queue option to false to ensure that our animations


wont pile up in a line waiting to execute if our user is hoverhappy. When you move to a different link, a new animation
will start regardless of whether the current one is finished or
not.
//Mouse Over Function
$('#navigation a').hover(function () {
$('#navigation_blob').animate(
{ width: $(this).width() + 10, = 10px more than #nav a
left: $(this).position().left},=Left Offset = Same
{ duration: 'slow',
as #nav as
easing: 'easeOutElastic',
queue:
false});

// Mouse out function


$('#navigation_blob')
.stop(true)
= stop animation (on Mouseout)
.animate(
{width: 'hide'},
= Hide its Width
{duration: 'slow',
easing: 'easeOutCirc',
queue: false} )
.animate(
= make it Disappear to the Left{left: $('#navigation li:first a').position().left;}, 'fast' );}
. stop stops the animation! It accepts two optional
parameters: clearQueue and gotoEnd. Were setting the
clearQueue parameter to true, so that any queued animations
are cleared.
The gotoEnd parameter is used if you want jQuery to
determine what an elements state will be at the end of the
current animation queue, and then jump immediately to that
state.

Animated Navigation, Take 2


*In Ex = our menu items will each have a hidden icon that will
bounce into view when the link is moused over
We achieve this by setting the list items height so that you can
only see the link text by default, but as we animate the height
the Hidden icon bounces into view.
Well start with the CSS: weve moved our menu to be absolutely positioned at
the top-right of the container div, where theres space for the icons to
expand. Weve set a background color for the icons to be set against, and
employed a clever trick to keep the background images out of view;
notice that the list items are 20px in height, but that the background is
offset 30px from the top. As a result, theyll be invisible until we expand
the height of the list items.
$(function() {
$('#navigation li').hover(function() {
= Mouseover
$(this)
.stop( true )
= Clears Animation Queue (so can Hover over other
<li>s??
.animate(
{height: '60px'},
{duration: 600, easing: 'easeOutBounce'}
)
}, function (){
= Mouseout
$(this)
.stop(true)
= Clears Animation Queue

20px

});

.animate(
{height: '20px'},

= Returns Height of <li> - to

{duration: 600, easing: 'easeOutCirc'}


)
});

The jQuery User Interface Library


The download builder is broken into several sections: Core,
Interaction, Widgets, Effects, and Themes.
Core is the main jQuery UI librarythe Widgets and
Interaction components all rely on it. A good way to approach
the builder is to deselect everything and then add only what
you require. If a component relies on another component to
function,it will be automatically selected for you.
While were developing, its safe to grab the full library. That
way everything will be there for us to use if we need it. Once youre
happy with the functionality on your web site, you can always
return to the download builder and create a custom library,
omitting anything unused.
*An Eg of JQ UI FX
$('p:first')
.effect('shake', {times:3}, 300)
.effect('highlight', {}, 3000)
.hide('explode', {}, 1000);
this is just a tiny sample of the available effects. Some of them
can only be used in this way, via the effect action, while
others can be used either in this way or in place of hide, show,
or toggle parameters. Some examples of the latter are blind, clip,
puff, fold, and slide.
Not all of the effects are pure flair, however, but many are
useful in common user interaction scenarios, such as
highlight, which is a standard way to indicate a new message
to the user
And if the jQuery UI assortment of effects just isnt enough for
you, never mindthere are hundreds more available from the
plugin repository!

Scrolling
The scroll Event

So, every time one of your users interacts with a scroll bar on
your site, an event will be fired that you can catch and respond
to.
#news {

height: 100px; - Small Height (to Force Scroll)


width: 300px;
overflow: scroll;

}
$('#news').scroll(function() { = <div> w/ Latest News
$('#header').append(
= Add to End of #header
'<span class="scrolled">You scrolled!</span>');});
Try scrolling in different ways: dragging the scroll bar, using
the mouse wheel, and clicking inside the scrollable zone to use
the arrow keys. In all the above cases, the scroll event will fire.

Floating Navigation
In Ex- main navigation element is always present at the top of
the visible part of the screen, regardless of the scroll position;
This is easy to implement using the scroll event: we simply
need to find out where we are on the page, and then move the
navigation to that point.
Our first task is to set up our CSS to prepare for the animated
navigation. Well add a position: relative;declaration to our
navigation element so that we can easily move it up and down
the page by adjusting its top property. For the purpose of this
exercise, weve applied a very large height property to the content
in order to force it to have a scroll bar
#navigation {
position: relative;
}
#content { height: 2000px;} = to Force a Scroll Bar- 4 Ex
$(window).scroll(function() {
$('#navigation').css('top', $(document).scrollTop());
});
.scrollTop
= Returns Top offset of = Matched El
To know where the top of the screen is we used the scrollTop
action. scrollTop returns the top offset of the matched
elementin our example we asked for the entire documents

top position: $(document).scrollTop(). This will always be the


very top of the screen.
The Above = works, sure, but its very jumpy
every time the user moves the scroll bar, it fires many scroll
events. Each one of those events triggers our code to update
the navigation positionso its no wonder the motion is jittery.
We saw how to stop animations from queuing up like this in the
section called Animated Navigation with the stop command.
This takes care of the jumpiness, but our effect could still use
some refinement. How about we smarten it up with some
animation and a little bit of bouncy easing =>
$(window).scroll(function() { = Scroll Event on Window
$('#navigation')
.stop()
= Clears Animation Queue
.animate({top: $(document).scrollTop()},'slow','easeOutBack');
});
= make TOP of #nav Same as Top of (document)

Scrolling the Document


*in Ex
Internal links at Top of Page to immediately jump to the correct
position for the menu item you selected. After the content,
theres often a link to take you back to the top of the screen
The first task is add the link to our pages footer. To jump to the
top of the page, all we need to do is set our links href attribute
to #.
If we think about it, all we want to do is animate the pages
scrolling position, which is represented by scrollTop in jQuery.
Well also need to cancel the default link actionotherwise the
page will jump before our animation has time to occur. If youre
new to JavaScript, theres an easy way to accomplish this: any
function handling a links click event need simply include the
statement return false to cancel the links default behavior:
$('a[href=#]').click(function() {
$('html').animate({scrollTop: 0},'slow'); = Returns to Top of Pg
return false; // Return false to cancel the default link action
}

BUT - If the users browser is operating in quirks mode, the $


('html')selector will fail.

So = use the The ScrollTo plugin, available from the plugin


repository,8 is a stable plugin for scrolling the screen and
overflowed elements.
$('a[href=#]').click(function() {
$.scrollTo(0,'slow'); - Scroll to Top of Pg
return false;
- to Cancel Links = Default Behaviour
});
The ScrollTo plugin is feature-packed and not limited to scrolling by an
integer value. You can pass in a relative value (like +=50px), a DOM element
(it will scroll the page to find that element), a selector string, a hash-value
containing x and y coordinates, or the keyword max, which will scroll to the
end of the document. You can scroll horizontally as well as vertically, and it also
has some great options for fine-tuning your destination. You can learn about all
these options on the plugins home page.9

Custom Scroll Bars


jScrollPane is a jQuery plugin that allows you to replace the
browsers default vertical scroll bars with custom ones in any
element with overflowed content.
There are two files we need to include: the JavaScript code file,
jScrollPane-1.2.3.min.js; and the accompanying CSS file,
jScrollPane.css
You can activate custom scroll bars on any element by simply
calling the jScrollPane function on it.
$('#fine_print').jScrollPane(
{ scrollbarWidth: 10,
scrollbarMargin: 10,
showArrows: false
});

Resizing
The resize Event
$(window).resize(function() {
alert("You resized the window!");
});

Layout Switcher
*In Ex = two separate, fixed-width layouts, and switch between
them by catching the resize event.

1. CSS
- Add body to Selectors to make = more
Specific (to override Existing Styles)
body #container { width:
850px;}
body #container p
{ width: 650px;}
body #header { background-image: url('../../css/images/header-corners-wide.png');}
body #celebs table { width: 650px; margin-left: 5px;
}

The next step = write the jQuery code to add or remove our new
style sheet.
if ($('body').width() > 900) {
$('<link rel="stylesheet" href="wide.css" type="text/css" />')
.appendTo('head');
} else {
$('link[href=wide.css]').remove();}

BUT= We need to run this code in two different situations:


once when we first load the page and then again whenever the
page is resized. You might be tempted to just copy and paste
that chunk of code, - DONT instead=>
Use a Function =>
$(document).ready(function() { = Run Func @ Doc =Ready
stylesheetToggle();
$(window).resize(stylesheetToggle); = & at W Resize
});
function stylesheetToggle() {
if ($('body').width() > 900) {
$('<link rel="stylesheet" href="wide.css" type="text/css" />')
.appendTo('head'); } else {$('link[href=wide.css]').remove(); } }
We only need to pass the functions name to the resize event
handler; since we are not declaring a function here, we have
no need for the the function keyword, or any curly braces or
parentheses.

Resizable Elements
The jQuery UI library contains a Resizable plugin as part of its
interaction functionality. The Resizable plugin makes elements that
you select able to be resized by adding a small handle (These are

styled in the jQuery UI style sheet) to the bottom corner of the


element.
Using the Resizable component in its most basic form is very
easy. We simply select the element or elements we want to
modify, and call the resizable function:
$('p').resizable();

Resizable textarea
$('textarea').resizable({ = 2 Resize Input Area
grid : [20, 20],
minWidth : 153,
minHeight : 30,
maxHeight : 220,
containment: 'parent'
= instead of maxWidth
});
- so can be as Wide as its Parent
The Resizable component is flexibile. It has a plethora of
configuration options, which you can explore in more detail on
the jQuery UI documentation site
Youll notice that weve omitted the maxWidth property in favor of the
containment parameter: this lets you specify a container restricting the
resizable element. You can use either a jQuery selector as the parameter or
the special keyword parent to refer to the resizable elements parent
element.
Weve also used the grid option to confine the resizable object to steps of a
certain size. For some reason, this seems to add a nice feel to the resizing
interaction. The
grid is specified as an array containing two elements: the horizontal grid size
and the vertical grid size.
One other parameter youll want to look into is the handles parameter. This
specifies which sides of the element the handles will be attached to and,
consequently, in which directions the element can be stretched. The
parameter accepts the following options: n, e, s, w, ne, se, sw, nw, and all. You
can specify any number of these by separating them with a comma. For
example, { handles : 'n', 'se'}adds handles to the top and bottom-right of the
element.

Pane Splitter
*In Ex =
to Display the companys terms and conditions. The problem is
that there are pages and pages of terms and conditions divided
into many subsectionsyet they need to be prominently

displayed on the home page. Perhaps a splitter could help us


out.
A splitter is a UI component that divides multiple areas on a
page in a way that allows users to resize elements; this way,
users are able to decide how much space they want to allot
each area. Splitters are commonplace in desktop
applications, and with the explosion of Rich Internet
Applications, theyre making their way onto the Web.
For now well focus solely on the resizing functionality.
Dynamically loading each sections content into the panes
will be covered in plenty of detail in Chapter 5.
1. HTML
<div id="splitter">
= Containing Div
<div class="pane" id="tocPane">
= T.O.Contents (4 Content)
<div class="inner">
.
.
</div>
</div>
<div class="pane" id="contentPane"> = Content
<div class="inner">
.
.
</div>
</div>
</div>
<!end #spliter (containg Div)
2. CSS
#splitter { height: 150px; margin-top: 30px; margin-bottom: 50px;}
#splitter .pane { width: 50%; height: 100%; float: left;}
#splitter h2 { margin-bottom: 0; padding-bottom: 0;}
#tocPane { overflow: hidden; background: #d6dde5 url(../images/handle.png) no-repeat
right center;}
#tocPane .inner width:
300px; }
#contentPane { overflow:
auto;}
#contentPane .inner { padding: 0 5px;}
3. J/Q

To create a horizontal splitter, we make the first element resizable and


specify an east-facing handleso only the right edge of the div will be
resizable.
If you were to run the example with only a simple resizable statement, youd
notice that were almost there: the two elements act somewhat like a split
paneexcept that the right elements width remains constant rather than
expanding to fill the
remaining space when you drag the handle. To take care of that, were
going to have to do some calculations inside the resizable widgets resize
function. This is an event handler that fires as the component is being
resized:

$('#splitter > div:first').resizable({ = Resizable Component


handles: 'e',
= Handle on East of Div
minWidth: '100',
maxWidth: '400',
resize: function() { = Resize Event Handler To Determine Size of Divs
var remainingSpace = $(this).parent().width() - $(this).outerWidth();
var divTwo = $(this).next();
var divTwoWidth = remainingSpace - (divTwo.outerWidth()divTwo.width()); divTwo.css('width', divTwoWidth + 'px');
}});

Every resizing will now also trigger a change in the second elements
width. A bit of basic math helps us work out what the widths should be: we
take the parent containers width (that is, the total width), then subtract the
first divs outerWidth. The outerWidth function is a useful way to grab the total
width of an element, including any padding and borders (it can also include
margins if you pass it the optional parameter true). Perhaps unsurprisingly, theres
a corresponding outerHeight function as well.
Having calculated how much space is left to use up, were almost ready to
set the first elements width. Theres just one remaining catch: if the
second div has borders or padding, we need to take these into consideration.
Unfortunately the outerWidth function is read-only, so were unable to use
it to set the total height.
To calculate how much of the elements width consists of borders and
padding, we need to subtract the elements outerWidth from its width.
Subtracting that from the remaining Space variable gives us exactly how
many pixels wide the second div needs to beand we can complete our
horizontal splitter.

If we then wanted to have a go at implementing a vertical splitter,


theres little to change: our pane elements stack on top of each other
(rather than side by side), and our resizable call uses a south-facing
handle instead of an east-facing one. The code is also almost identical
but now were interested in the elements heights, not widths:

$('#splitter > div:first').resizable({


handles: 's',
minHeight: '50',
maxHeight: '200',
resize: function() {
var remainingSpace = $(this).parent().height()
$(this).outerHeight();

var divTwo = $(this).next();

var divTwoHeight = remainingSpace


(divTwo.outerHeight() - divTwo.height());

divTwo.css('height', divTwoHeight + 'px');


}});

These simple splitters are quite useful, require very little code, and will be
suitable for many purposes. But if you require complex splitter behavior, such
as multiple split panes or nested panes, head over to the plugin repository
and check out the jQuery Splitter plugin.

You might also like