Sunteți pe pagina 1din 111

5/18/12

jQuery Fundamentals

jQuery Fundamentals
By Rebecca Murphey http://github.com/rmurphey/jqfundamentals With contributions by James Padolsey, Paul Irish, and others. See the GitHub repository for a complete history of contributions.
Copyright 2011 Licensed by Rebecca Murphey under the Creative Commons Attribution-Share Alike 3.0 United States license. You are free to copy, distribute, transmit, and remix this work, provided you attribute the work to Rebecca Murphey as the original author and reference the GitHub repository for the work. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license. Any of the above conditions can be waived if you get permission from the copyright holder. For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to the license.

Reporting Issues
Your feedback is essential to improving jQuery Fundamentals; if you see an error or an opportunity for improvement, please open an issue.

Suggesting Changes to Content


If youd like to suggest a change to the book, the strong preference is that you submit a pull request rather than describing your proposed change in an issue. Once a pull request is submitted, it will be reviewed for inclusion.

Suggesting Additions to Content


If youve come across a blog post or other resource that would be great for inclusion in jQuery Fundamentals, please open an issue with a link to the resource, and indicate in the issue whether youve already discussed inclusion of the resource with the author.

Contributing Content
jqfundamentals.com/book/index.html#chapter-1 1/111

5/18/12

jQuery Fundamentals

Contributions to jQuery Fundamentals are always welcome. The best way to submit your content for consideration is to submit a pull request.

Contents
Chapter 1: Welcome Chapter 2: JavaScript Basics Chapter 3: jQuery Basics Chapter 4: jQuery Core Chapter 5: Events Chapter 6: Effects Chapter 7: Ajax Chapter 8: Plugins Chapter 9: Performance Best Practices Chapter 10: Code Organization Chapter 11: Custom Events

List of Examples
Example 1.1: An example of inline JavaScript Example 1.2: An example of including external JavaScript Example 1.3: Example of an example Example 2.1: A simple variable declaration Example 2.2: Whitespace has no meaning outside of quotation marks Example 2.3: Parentheses indicate precedence Example 2.4: Tabs enhance readability, but have no special meaning Example 2.5: Concatenation Example 2.6: Multiplication and division Example 2.7: Incrementing and decrementing Example 2.8: Addition vs. concatenation Example 2.9: Forcing a string to act as a number Example 2.10: Forcing a string to act as a number (using the unary-plus operator) Example 2.11: Logical AND and OR operators Example 2.12: Comparison operators Example 2.13: Flow control Example 2.14: Values that evaluate to true Example 2.15: Values that evaluate to false Example 2.16: The ternary operator Example 2.17: A switch statement Example 2.18: Loops Example 2.19: A typical for loop Example 2.20: A typical while loop Example 2.21: A while loop with a combined conditional and incrementer Example 2.22: A do-while loop Example 2.23: Stopping a loop Example 2.24: Skipping to the next iteration of a loop Example 2.25: A simple array Example 2.26: Accessing array items by index Example 2.27: Testing the size of an array Example 2.28: Changing the value of an array item Example 2.29: Adding elements to an array Example 2.30: Working with arrays
jqfundamentals.com/book/index.html#chapter-1 2/111

5/18/12

jQuery Fundamentals

Example 2.31: Creating an "object literal" Example 2.32: Function Declaration Example 2.33: Named Function Expression Example 2.34: A simple function Example 2.35: A function that returns a value Example 2.36: A function that returns another function Example 2.37: A self-executing anonymous function Example 2.38: Passing an anonymous function as an argument Example 2.39: Passing a named function as an argument Example 2.40: Testing the type of various variables Example 2.41: A function invoked using Function.call Example 2.42: A function created using Function.bind Example 2.43: A function being attached to an object at runtime Example 2.44: Functions have access to variables defined in the same scope Example 2.45: Code outside the scope in which a variable was defined does not have access to the variable Example 2.46: Variables with the same name can exist in different scopes with different values Example 2.47: Functions can "see" changes in variable values after the function is defined Example 2.48: Scope insanity Example 2.49: How to lock in the value of i? Example 2.50: Locking in the value of i with a closure Example 2.51: Using a closure to access inner and outer object instances simultaneously Example 3.1: A $(document).ready() block Example 3.2: Shorthand for $(document).ready() Example 3.3: Passing a named function instead of an anonymous function Example 3.4: Selecting elements by ID Example 3.5: Selecting elements by class name Example 3.6: Selecting elements by attribute Example 3.7: Selecting elements by compound CSS selector Example 3.8: Pseudo-selectors Example 3.9: Testing whether a selection contains elements Example 3.10: Storing selections in a variable Example 3.11: Refining selections Example 3.12: Using form-related pseduo-selectors Example 3.13: Chaining Example 3.14: Formatting chained code Example 3.15: Restoring your original selection using $.fn.end Example 3.16: The $.fn.html method used as a setter Example 3.17: The html method used as a getter Example 3.18: Getting CSS properties Example 3.19: Setting CSS properties Example 3.20: Working with classes Example 3.21: Basic dimensions methods Example 3.22: Setting attributes Example 3.23: Getting attributes Example 3.24: Moving around the DOM using traversal methods Example 3.25: Iterating over a selection Example 3.26: Changing the HTML of an element Example 3.27: Moving elements using different approaches Example 3.28: Making a copy of an element
jqfundamentals.com/book/index.html#chapter-1 3/111

5/18/12

jQuery Fundamentals

Example 3.29: Creating new elements Example 3.30: Creating a new element with an attribute object Example 3.31: Getting a new element on to the page Example 3.32: Creating and adding an element to the page at the same time Example 3.33: Manipulating a single attribute Example 3.34: Manipulating multiple attributes Example 3.35: Using a function to determine an attribute's new value Example 4.1: Checking the type of an arbitrary value Example 4.2: Storing and retrieving data related to an element Example 4.3: Storing a relationship between elements using $.fn.data Example 4.4: Putting jQuery into no-conflict mode Example 4.5: Using the $ inside a self-executing anonymous function Example 5.1: Event binding using a convenience method Example 5.2: Event biding using the $.fn.bind method Example 5.3: Event binding using the $.fn.bind method with data Example 5.4: Switching handlers using the $.fn.one method Example 5.5: Unbinding all click handlers on a selection Example 5.6: Unbinding a particular click handler Example 5.7: Namespacing events Example 5.8: Binding Multiple Events Example 6.1: A basic use of a built-in effect Example 6.2: Setting the duration of an effect Example 6.3: Augmenting jQuery.fx.speeds with custom speed definitions Example 6.4: Running code when an animation is complete Example 6.5: Run a callback even if there were no elements to animate Example 6.6: Custom effects with $.fn.animate Example 6.7: Per-property easing Example 7.1: Using the core $.ajax method Example 7.2: Using jQuery's Ajax convenience methods Example 7.3: Using $.fn.load to populate an element Example 7.4: Using $.fn.load to populate an element based on a selector Example 7.5: Turning form data into a query string Example 7.6: Creating an array of objects containing form data Example 7.7: Using YQL and JSONP Example 7.8: Setting up a loading indicator using Ajax Events Example 8.1: Creating a plugin to add and remove a class on hover Example 8.2: The Mike Alsup jQuery Plugin Development Pattern Example 8.3: A simple, stateful plugin using the jQuery UI widget factory Example 8.4: Passing options to a widget Example 8.5: Setting default options for a widget Example 8.6: Creating widget methods Example 8.7: Calling methods on a plugin instance Example 8.8: Responding when an option is set Example 8.9: Providing callbacks for user extension Example 8.10: Binding to widget events Example 8.11: Adding a destroy method to a widget
jqfundamentals.com/book/index.html#chapter-1 4/111

5/18/12

jQuery Fundamentals

Example 10.1: An object literal Example 10.2: Using an object literal for a jQuery feature Example 10.3: The module pattern Example 10.4: Using the module pattern for a jQuery feature Example 10.5: Using RequireJS: A simple example Example 10.6: A simple JavaScript file with dependencies Example 10.7: Defining a RequireJS module that has no dependencies Example 10.8: Defining a RequireJS module with dependencies Example 10.9: Defining a RequireJS module that returns a function

Back to top

Welcome
jQuery is fast becoming a must-have skill for front-end developers. The purpose of this book is to provide an overview of the jQuery JavaScript library; when you're done with the book, you should be able to complete basic tasks using jQuery, and have a solid basis from which to continue your learning. This book was designed as material to be used in a classroom setting, but you may find it useful for individual study. This is a hands-on class. We will spend a bit of time covering a concept, and then youll have the chance to work on an exercise related to the concept. Some of the exercises may seem trivial; others may be downright daunting. In either case, there is no grade; the goal is simply to get you comfortable working your way through problems youll commonly be called upon to solve using jQuery. Example solutions to all of the exercises are included in the sample code.

Getting the Code


The code well be using in this book is hosted in a repository on Github. You can download a .zip or .tar file of the code, then uncompress it to use it on your server. If youre git-inclined, youre welcome to clone or fork the repository.

Software
You'll want to have the following tools to make the most of the class: The Firefox browser
jqfundamentals.com/book/index.html#chapter-1 5/111

5/18/12

jQuery Fundamentals

The Firebug extension for Firefox A plain text editor For the Ajax portions: A local server (such as MAMP or WAMP), or an FTP or SSH client to access a remote server.

Adding JavaScript to Your Page


JavaScript can be included inline or by including an external file via a script tag. The order in which you include JavaScript is important: dependencies must be included before the script that depends on them. For the sake of page performance, JavaScript should be included as close to the end of your HTML as is practical. Multiple JavaScript files should be combined for production use.
Example 1.1: An example of inline JavaScript

1 <cit srp> 2 cnoelg'el'; osl.o(hlo) 3 <srp> /cit


Example 1.2: An example of including external JavaScript

1 <citsc'j/qeyj'<srp> srp r=/sjur.s>/cit

JavaScript Debugging
A debugging tool is essential for JavaScript development. Firefox provides a debugger via the Firebug extension; Safari and Chrome provide built-in consoles. Each console offers: single- and multi-line editors for experimenting with JavaScript an inspector for looking at the generated source of your page a Network or Resources view, to examine network requests When you are writing JavaScript code, you can use the following methods to send messages to the console:
c n o e l g )for sending general log messages osl.o( c n o e d r )for logging a browseable object osl.i( c n o e w r ( for logging warnings osl.an) c n o e e r r )for logging error messages osl.ro(

Other console methods are also available, though they may differ
jqfundamentals.com/book/index.html#chapter-1 6/111

5/18/12

jQuery Fundamentals

from one browser to another. The consoles also provide the ability to set break points and watch expressions in your code for debugging purposes.

Exercises
Most chapters in the book conclude with one or more exercises. For some exercises, youll be able to work directly in Firebug; for others, you will need to include other scripts after the jQuery script tag as directed in the individual exercises. In some cases, you will need to consult the jQuery documentation in order to complete an exercise, as we wont have covered all of the relevant information in the book. This is by design; the jQuery library is large, and learning to find answers in the documentation is an important part of the process. Here are a few suggestions for tackling these problems: First, make sure you thoroughly understand the problem you're being asked to solve. Next, figure out which elements you'll need to access in order to solve the problem, and determine how you'll get those elements. Use Firebug to verify that you're getting the elements you're after. Finally, figure out what you need to do with the elements to solve the problem. It can be helpful to write comments explaining what you're going to do before you try to write the code to do it. Do not be afraid to make mistakes! Do not try to make your code perfect on the first try! Making mistakes and experimenting with solutions is part of learning the library, and youll be a better developer for it. Examples of solutions for these exercises are located in the / o u i n directory in the sample code. sltos

Conventions used in this book


Methods that can be called on jQuery objects will be referred to as $ f . e h d a e Methods that exist in the jQuery .nmtoNm. namespace but that cannot be called on jQuery objects will be referred to as $ m t o N m . If this doesn't mean much to you, .ehdae don't worry it should become clearer as you progress through the book.
Example 1.3: Example of an example

1 / cd eape wl apa lk ti / oe xmls il per ie hs


jqfundamentals.com/book/index.html#chapter-1 7/111

5/18/12

jQuery Fundamentals

Remarks will appear like this.

Note
Notes about a topic will appear like this.

Reference Material
There are any number of articles and blog posts out there that address some aspect of jQuery. Some are phenomenal; some are downright wrong. When you read an article about jQuery, be sure it's talking about the same version as you're using, and resist the urge to just copy and paste take the time to understand the code in the article. Here are some excellent resources to use during your jQuery learning. The most important of all is the jQuery source itself: it contains, in code form, complete documentation of the library. It is not a black box your understanding of the library will grow exponentially if you spend some time visiting it now and again and I highly recommend bookmarking it in your browser and referring to it often. The jQuery source jQuery documentation jQuery forum Delicious bookmarks #jquery IRC channel on Freenode

Part I. JavaScript 101


Back to top

JavaScript Basics
Overview
jqfundamentals.com/book/index.html#chapter-1 8/111

5/18/12

jQuery Fundamentals

jQuery is built on top of JavaScript, a rich and expressive language in its own right. This section covers the basic concepts of JavaScript, as well as some frequent pitfalls for people who have not used JavaScript before. While it will be of particular value to people with no programming experience, even people who have used other programming languages may benefit from learning about some of the peculiarities of JavaScript. If youre interested in learning more about the JavaScript language, I highly recommend JavaScript: The Good Parts by Douglas Crockford.

Syntax Basics
Understanding statements, variable naming, whitespace, and other basic JavaScript syntax.
Example 2.1: A simple variable declaration

1 vrfo='el wrd; a o hlo ol'


Example 2.2: Whitespace has no meaning outside of quotation marks

1 vrfo= a o

'el wrd; hlo ol'

Example 2.3: Parentheses indicate precedence

1 2*3+5 ; / rtrs1;mlilcto / eun 1 utpiain hpesfrt apn is 2 2*( +5; / rtrs1;adto 3 ) / eun 6 diin hpesfrt apn is
Example 2.4: Tabs enhance readability, but have no special meaning

1 vrfo=fnto( { a o ucin) 2 cnoelg'el'; osl.o(hlo) 3 } ;

Operators
Basic Operators
Basic operators allow you to manipulate values.
Example 2.5: Concatenation

1 vrfo='el' a o hlo; 2 vrbr='ol' a a wrd; 3 4 cnoelgfo+''+br;/ 'el osl.o(o a) / hlo wrd ol'
Example 2.6: Multiplication and division

1 2*3 ; 2 2/3 ;
jqfundamentals.com/book/index.html#chapter-1 9/111

5/18/12

jQuery Fundamentals

Example 2.7: Incrementing and decrementing

1 vri=1 a ; 2 3 vrj=+i / peiceet jeul a +; / r-nrmn: qas 2 ieul 2 ; qas 4 vrk=i+ / ps-nrmn:keul a +; / oticeet qas 2 ieul 3 ; qas

Operations on Numbers & Strings


In JavaScript, numbers and strings will occasionally behave in ways you might not expect.
Example 2.8: Addition vs. concatenation

1 vrfo=1 a o ; 2 vrbr='' a a 2; 3 4 cnoelgfo+br; / 1.u o osl.o(o a) / 2 h h


Example 2.9: Forcing a string to act as a number

1 2 3 4 5

vrfo=1 a o ; vrbr='' a a 2; / cec tesrn t anme / ore h tig o ubr cnoelgfo+Nme(a); osl.o(o ubrbr)

The Number constructor, when called as a function (like above) will have the effect of casting its argument into a number. You could also use the unary plus operator, which does the same thing:
Example 2.10: Forcing a string to act as a number (using the unary-plus operator)

1 cnoelgfo++a) osl.o(o br;

Logical Operators
Logical operators allow you to evaluate a series of operands using AND and OR operations.
Example 2.11: Logical AND and OR operators

0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 1 0

vrfo=1 a o ; vrbr=0 a a ; vrbz=2 a a ; fo| br o | a; br| fo a | o; fo& br o & a; fo& bz o & a; bz& fo a & o; / rtrs1 wihi tu / eun , hc s re / rtrs1 wihi tu / eun , hc s re / rtrs0 wihi fle / eun , hc s as / rtrs2 wihi tu / eun , hc s re / rtrs1 wihi tu / eun , hc s re

Though it may not be clear from the example, the | operator |


jqfundamentals.com/book/index.html#chapter-1 10/111

5/18/12

jQuery Fundamentals

returns the value of the first truthy operand, or, in cases where neither operand is truthy, it'll return the last of both operands. The & operator returns the value of the first false operand, or & the value of the last operand if both operands are truthy. Be sure to consult the section called Truthy and Falsy Things for more details on which values evaluate to t u and which re evaluate to f l e as.

Note
You'll sometimes see developers use these logical operators for flow control instead of using i statements. For example: f 1 / d smtigwt foi foi / o oehn ih o f o s tuh rty 2 fo& dSmtigfo; o & ooehn(o) 3 4 / stbrt bzi bzi tuh; / e a o a f a s rty 5 / ohrie sti t tertr / tews, e t o h eun 6 / vleo cetBr) / au f raea( 7 vrbr=bz| cetBr) a a a | raea(; This style is quite elegant and pleasantly terse; that said, it can be really hard to read, especially for beginners. I bring it up here so you'll recognize it in code you read, but I don't recommend using it until you're extremely comfortable with what it means and how you can expect it to behave.

Comparison Operators
Comparison operators allow you to test whether values are equivalent or whether values are identical.
Example 2.12: Comparison operators

0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6

vrfo=1 a o ; vrbr=0 a a ; vrbz='' a a 1; vrbm=2 a i ; fo= br o = a; fo! br o = a; fo= bz o = a; / rtrsfle / eun as / rtrstu / eun re / rtrstu;crfl / eun re aeu! / rtrsfle / eun as / rtrstu / eun re / rtrstu / eun re

fo==bz o = a; fo!=bz o = a; fo==pren(a) o = asItbz; fo>bm o i; bm>bz i a; fo< bz o = a;

/ rtrsfle / eun as / rtrstu / eun re / rtrstu / eun re

Conditional Code
jqfundamentals.com/book/index.html#chapter-1 11/111

5/18/12

jQuery Fundamentals

Sometimes you only want to run a block of code under certain conditions. Flow control via i and e s blocks lets you run f le code only under certain conditions.
Example 2.13: Flow control

0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 1 0 1 1 1 2 1 3 1 4 1 5

vrfo=tu; a o re vrbr=fle a a as; i (a){ f br / ti cd wl nvrrn / hs oe il ee u cnoelg'el!) osl.o(hlo'; }

i (a){ f br / ti cd wntrn / hs oe o' u }es { le i (o){ f fo / ti cd wl rn / hs oe il u }es { le / ti cd wudrni foad / hs oe ol u f o n brwr bt fle a ee oh as 1 6 } 1 } 7

Note
While curly braces aren't strictly required around single-line i statements, using them consistently, even when they f aren't strictly required, makes for vastly more readable code. Be mindful not to define functions with the same name multiple times within separate i / e s blocks, as doing so f le may not have the expected result.

Truthy and Falsy Things


In order to use flow control successfully, it's important to understand which kinds of values are "truthy" and which kinds of values are "falsy." Sometimes, values that seem like they should evaluate one way actually evaluate another.
Example 2.14: Values that evaluate to true

1 2 3 4 5

'' 0; 'n srn' ay tig; [; / a epyary ] / n mt ra {; / a epyojc } / n mt bet 1 ; / aynnzr nme / n o-eo ubr

Example 2.15: Values that evaluate to false

1 0 ;
jqfundamentals.com/book/index.html#chapter-1 12/111

5/18/12

jQuery Fundamentals

2 '; / avmtptigtanme" '; nacits" 3 NN /J epysrno--ubr a a Sr ' n vral aibe 4 nl; ul 5 udfnd / b crfl- udfndcn neie; / e aeu - neie a b rdfnd e eeie!

Conditional Variable Assignment with The Ternary Operator


Sometimes you want to set a variable to a value depending on some condition. You could use an i / e s statement, but in f le many cases the ternary operator is more convenient. [Definition: The ternary operator tests a condition; if the condition is true, it returns a certain value, otherwise it returns a different value.]
Example 2.16: The ternary operator

1 / stfot 1i bri tu; / e o o f a s re 2 / ohrie stfot 0 / tews, e o o 3 vrfo=br?1:0 a o a ; While the ternary operator can be used without assigning the return value to a variable, this is generally discouraged.

Switch Statements
Rather than using a series of if/else if/else blocks, sometimes it can be useful to use a switch statement instead. [Definition: Switch statements look at the value of a variable or expression, and run different blocks of code depending on the value.]
Example 2.17: A switch statement

0 sic (o){ 1 wth fo 0 2 0 3 cs 'a' ae br: 0 4 aet'h vlewsbr- yy'; lr(te au a a - a!) 0 5 bek ra; 0 6 0 7 cs 'a' ae bz: 0 8 aet'o bz:'; lr(bo a () 0 9 bek ra; 1 0 1 1 dfut eal: 1 2 aet'vrtiges i js lr(eeyhn le s ut o'; k) 1 3 bek ra; 1 4 1 } 5 Switch statements have somewhat fallen out of favor in JavaScript, because often the same behavior can be accomplished by creating an object that has more potential for reuse, testing, etc. For example: 0 vrsufoo={ 1 a tfTD 0 2 'a':fnto( { br ucin)
jqfundamentals.com/book/index.html#chapter-1 13/111

5/18/12

jQuery Fundamentals

0 3 0 4 0 5 0 6 0 7 0 8 0 9 1 0 1 1

} ,

aet'h vlewsbr- yy'; lr(te au a a - a!)

'a':fnto( { bz ucin) aet'o bz:'; lr(bo a () } ,

'eal':fnto( { dfut ucin) aet'vrtiges i js lr(eeyhn le s ut o'; k) 1 2 } 1 } 3 ; 1 4 1 i (tfTD[o] { 5 f sufoofo) 1 6 sufoofo(; tfTD[o]) 1 }es { 7 le 1 8 sufoo'eal'(; tfTD[dfut]) 1 } 9 We'll look at objects in greater depth later in this chapter.

Loops
Loops let you run a block of code a certain number of times.
Example 2.18: Loops

1 / lg 'r 0,'r 1,.. 'r 4 / os ty ' ty ' ., ty ' 2 fr(a i0 i5 i+ { o vr =; <; +) 3 cnoelg'r '+i; osl.o(ty ) 4 } Note that in Loops even though we use the keyword var before the variable name i this does not "scope" the variable ito the , loop block. We'll discuss scope in depth later in this chapter.

The for loop


A f rloop is made up of four statements and has the following o structure: 1 fr(iiilsto] [odtoa] o [ntaiain; cniinl; [trto] ieain) 2 [opoy loBd] The initialisation statement is executed only once, before the loop starts. It gives you an opportunity to prepare or declare any variables. The conditional statement is executed before each iteration, and its return value decides whether or not the loop is to continue. If the conditional statement evaluates to a falsey value then the loop stops. The iteration statement is executed at the end of each iteration and gives you an opportunity to change the state of important variables. Typically, this will involve incrementing or
jqfundamentals.com/book/index.html#chapter-1 14/111

5/18/12

jQuery Fundamentals

decrementing a counter and thus bringing the loop ever closer to its end. The loopBody statement is what runs on every iteration. It can contain anything you want. You'll typically have multiple statements that need to be executed and so will wrap them in a block ( { . } . . ). Here's a typical f rloop: o
Example 2.19: A typical for loop

1 fr(a i=0 lmt=10 i<lmt o vr , ii 0; ii; i+ { +) 2 / Ti bokwl b eeue 10 / hs lc il e xctd 0 tms ie 3 cnoelg'urnl a '+i; osl.o(Crety t ) 4 / Nt:tels lgwl b / oe h at o il e "urnl a 9" Crety t 9 5 }

The while loop


A w i eloop is similar to an i statement, except that its body hl f will keep executing until the condition evaluates to false. 1 wie(cniinl)[opoy hl [odtoa] loBd] Here's a typical w i eloop: hl
Example 2.20: A typical while loop

1 vri=0 a ; 2 wie( <10 { hl i 0) 3 4 / Ti bokwl b eeue 10 / hs lc il e xctd 0 tms ie 5 cnoelg'urnl a '+i; osl.o(Crety t ) 6 7 i+ / iceeti +; / nrmn 8 9 } You'll notice that we're having to increment the counter within the loop's body. It is possible to combine the conditional and incrementer, like so:
Example 2.21: A while loop with a combined conditional and incrementer

1 vri=-; a 1 2 wie(+ <10 { hl +i 0) 3 / Ti bokwl b eeue 10 / hs lc il e xctd 0 tms ie 4 cnoelg'urnl a '+i; osl.o(Crety t ) 5 } Notice that we're starting at - and using the prefix incrementer 1 (+ i + ).
jqfundamentals.com/book/index.html#chapter-1 15/111

5/18/12

jQuery Fundamentals

The do-while loop


This is almost exactly the same as the w i eloop, except for the hl fact that the loop's body is executed at least once before the condition is tested. 1 d [opoy wie(cniinl) o loBd] hl [odtoa] Here's a d - h l loop: owie
Example 2.22: A do-while loop

1 d { o 2 3 / Ee tog tecniineauts / vn huh h odto vlae t fle o as 4 / ti lo' bd wl sileeue / hs ops oy il tl xct oc. ne 5 6 aet'itee'; lr(H hr!) 7 8 }wie(as) hl fle; These types of loops are quite rare since only few situations require a loop that blindly executes at least once. Regardless, it's good to be aware of it.

Breaking and continuing


Usually, a loop's termination will result from the conditional statement not evaluating to true, but it is possible to stop a loop in its tracks from within the loop's body with the b e k ra statement.
Example 2.23: Stopping a loop

1 fr(a i=0 i<1;i+ { o vr ; 0 +) 2 i (oehn){ f smtig 3 bek ra; 4 5 } }

You may also want to continue the loop without executing more of the loop's body. This is done using the c n i u statement. otne
Example 2.24: Skipping to the next iteration of a loop

0 fr(a i=0 i<1;i+ { 1 o vr ; 0 +) 0 2 0 3 i (oehn){ f smtig 0 4 cniu; otne 0 5 } 0 6 0 7 / Tefloigsaeetwl ol b / h olwn ttmn il ny e eeue xctd 0 8 / i tecniinl'oehn'hs / f h odtoa smtig a
jqfundamentals.com/book/index.html#chapter-1 16/111

5/18/12

jQuery Fundamentals

ntbe mt o en e 0 9 cnoelg' hv be rahd) osl.o(I ae en ece'; 1 0 1 } 1

Reserved Words
JavaScript has a number of reserved words, or words that have special meaning in the language. You should avoid using these words in your code except when using them with their intended meaning.
asrc btat boen ola bek ra bt ye cs ae cth ac ca hr cas ls cnt os cniu otne dbge eugr dfut eal dlt eee d o dul obe es le eu nm epr xot etns xed fnl ia fnly ial fot la fr o fnto ucin gt oo i f ipeet mlmns ipr mot i n isaco ntnef it n itrae nefc ln og ntv aie nw e pcae akg piae rvt poetd rtce pbi ulc rtr eun sot hr sai ttc spr ue sic wth snhoie ycrnzd
jqfundamentals.com/book/index.html#chapter-1 17/111

5/18/12

jQuery Fundamentals

ti hs trw ho trw hos taset rnin ty r tpo yef vr a vi od vltl oaie wie hl wt ih

Arrays
Arrays are zero-indexed lists of values. They are a handy way to store a set of related items of the same type (such as strings), though in reality, an array can include multiple types of items, including other arrays.
Example 2.25: A simple array

1 vrmAry=['el' 'ol'] a yra hlo, wrd ;


Example 2.26: Accessing array items by index

1 vrmAry=['el' 'ol' 'o' a yra hlo, wrd, fo, 'a'] br ; 2 cnoelgmAry3) osl.o(yra[]; / lg 'a' / os br
Example 2.27: Testing the size of an array

1 vrmAry=['el' 'ol'] a yra hlo, wrd ; 2 cnoelgmArylnt) osl.o(yra.egh; / lg 2 / os


Example 2.28: Changing the value of an array item

1 vrmAry=['el' 'ol'] a yra hlo, wrd ; 2 mAry1 ='hne' yra[] cagd; While it's possible to change the value of an array item as shown in Changing the value of an array item, it's generally not advised.
Example 2.29: Adding elements to an array

1 vrmAry=['el' 'ol'] a yra hlo, wrd ; 2 mAryps(nw) yra.uh'e';


Example 2.30: Working with arrays

1 vrmAry=['' '' '' '' ''] a yra h, e, l, l, o ; 2 vrmSrn =mAryji('; / a ytig yra.on') / 'el' hlo 3 vrmSlt=mSrn.pi('; / [ a ypi ytigslt') / '' '' '' '' ''] h, e, l, l, o

Objects
jqfundamentals.com/book/index.html#chapter-1 18/111

5/18/12

jQuery Fundamentals

Objects contain one or more key-value pairs. The key portion can be any string. The value portion can be any type of value: a number, a string, an array, a function, or even another object. [Definition: When one of these values is a function, its called a method of the object.] Otherwise, they are called properties. As it turns out, nearly everything in JavaScript is an object arrays, functions, numbers, even strings and they all have properties and methods.
Example 2.31: Creating an "object literal"

0 vrmOjc ={ 1 a ybet 0 2 syel :fnto( { aHlo ucin) 0 3 cnoelg'el'; osl.o(hlo) 0 4 } , 0 5 0 6 mNm :'eec' yae Rbca 0 } 7 ; 0 8 0 mOjc.aHlo) 9 ybetsyel(; 'el' hlo 1 cnoelgmOjc.yae; 0 osl.o(ybetmNm) 'eec' Rbca

/ lg / os / lg / os

Note
When creating object literals, you should note that the key portion of each key-value pair can be written as any valid JavaScript identifier, a string (wrapped in quotes) or a number: 1 vrmOjc ={ a ybet 2 vlddniir 13 aiIetfe: 2, 3 'oesrn' 46 sm tig: 5, 4 999 79 99: 8 5 } ; Object literals can be extremely useful for code organization; for more information, read Using Objects to Organize Your Code by Rebecca Murphey.

Functions
Functions contain blocks of code that need to be executed repeatedly. Functions can take zero or more arguments, and can optionally return a value. Functions can be created in a variety of ways:
Example 2.32: Function Declaration

jqfundamentals.com/book/index.html#chapter-1

19/111

5/18/12

jQuery Fundamentals

1 fnto fo){/ d smtig* } ucin o( * o oehn /


Example 2.33: Named Function Expression

1 vrfo=fnto( {/ d smtig* } a o ucin) * o oehn / I prefer the named function expression method of setting a function's name, for some rather in-depth and technical reasons. You are likely to see both methods used in others' JavaScript code.

Using Functions
Example 2.34: A simple function

1 vrget=fnto(esn getn){ a re ucinpro, reig 2 vrtx =getn +' '+pro; a et reig , esn 3 cnoelgtx) osl.o(et; 4 } ; 5 6 7 get'eec' 'el'; re(Rbca, Hlo)
Example 2.35: A function that returns a value

1 vrget=fnto(esn getn){ a re ucinpro, reig 2 vrtx =getn +' '+pro; a et reig , esn 3 rtr tx; eun et 4 } ; 5 6 cnoelgget'eec''el') osl.o(re(Rbca,hlo);
Example 2.36: A function that returns another function

1 vrget=fnto(esn getn){ a re ucinpro, reig 2 vrtx =getn +' '+pro; a et reig , esn 3 rtr fnto( {cnoelgtx) eun ucin) osl.o(et; } ; 4 } ; 5 6 7 vrgetn =get'eec' 'el'; a reig re(Rbca, Hlo) 8 getn(; reig)

Self-Executing Anonymous Functions


A common pattern in JavaScript is the self-executing anonymous function. This pattern creates a function expression and then immediately executes the function. This pattern is extremely useful for cases where you want to avoid polluting the global namespace with your code no variables declared inside of the function are visible outside of it.
Example 2.37: A self-executing anonymous function

1 (ucin) fnto({ 2 vrfo='el wrd; a o Hlo ol' 3 }(; )) 4


jqfundamentals.com/book/index.html#chapter-1 20/111

5/18/12

jQuery Fundamentals

5 cnoelgfo; 6 osl.o(o)

/ udfnd / neie!

Functions as Arguments
In JavaScript, functions are "first-class citizens" &mdash they can be assigned to variables or passed to other functions as arguments. Passing functions as arguments is an extremely common idiom in jQuery.
Example 2.38: Passing an anonymous function as an argument

1 vrmF =fnto(n { a yn ucinf) 2 vrrsl =f(; a eut n) 3 cnoelgrsl) osl.o(eut; 4 } ; 5 6 mF(ucin){rtr 'el wrd; ynfnto( eun hlo ol' }; / lg 'el wrd ) / os hlo ol'
Example 2.39: Passing a named function as an argument

0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 1 0

vrmF =fnto(n { a yn ucinf) vrrsl =f(; a eut n) cnoelgrsl) osl.o(eut; } ; vrmOhrn=fnto( { a yteF ucin) rtr 'el wrd; eun hlo ol' } ; mF(yteF) ynmOhrn; / lg 'el wrd / os hlo ol'

Testing Type
JavaScript offers a way to test the "type" of a variable. However, the result can be confusing for example, the type of an Array is "object". It's common practice to use the t p o operator when trying to yef determining the type of a specific value.
Example 2.40: Testing the type of various variables

0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6

vrmFnto =fnto( { a yucin ucin) cnoelg'el'; osl.o(hlo) } ; vrmOjc ={ a ybet fo:'a' o br } ; vrmAry=['' '' ''] a yra a, b, c ; vrmSrn ='el' a ytig hlo; vrmNme =3 a yubr ; tpo mFnto; yef yucin tpo mOjc; yef ybet / rtrs'ucin / eun fnto' / rtrs'bet / eun ojc'
21/111

jqfundamentals.com/book/index.html#chapter-1

5/18/12

jQuery Fundamentals

1 tpo mAry 7 yef yra; / rtrs'bet / eun ojc' crfl aeu! 1 tpo mSrn; 8 yef ytig / rtrs'tig; / eun srn' 1 tpo mNme; 9 yef yubr / rtrs'ubr / eun nme' 2 0 2 tpo nl; 1 yef ul / rtrs'bet / eun ojc' crfl aeu! 2 2 2 3 2 i (yra.uh& mArysie& 4 f mAryps & yra.lc & mAryji){ yra.on 2 5 / poal a ary / rbby n ra 2 6 / (hsi cle "uktpn" / ti s ald dc yig) 2 } 7 2 8 2 i (betpooyetSrn.almAry 9 f Ojc.rttp.otigcl(yra) =='ojc Ary' { = [bet ra]) 3 0 / Dfntl a ary / eiiey n ra! 3 1 / Ti i wdl cniee a te / hs s iey osdrd s h ms rbs wy ot out a 3 2 / t dtriei aseii vlei / o eemn f pcfc au s a Ary n ra. 3 } 3 jQuery offers utility methods to help you determine the type of an arbitrary value. These will be covered later.

The t i keyword hs
In JavaScript, as in most object-oriented programming languages, t i is a special keyword that is used within methods hs to refer to the object on which a method is being invoked. The value of t i is determined using a simple series of steps: hs 1. If the function is invoked using Function.call or Function.apply, t i will be set to the first argument hs passed to call/apply. If the first argument passed to call/apply is n l or u d f n d t i will refer to the global ul neie, hs object (which is the w n o object in Web browsers). idw 2. If the function being invoked was created using Function.bind, t i will be the first argument that was hs passed to bind at the time the function was created. 3. If the function is being invoked as a method of an object, t i will refer to that object. hs 4. Otherwise, the function is being invoked as a standalone function not attached to any object, and t i will refer to hs the global object.
Example 2.41: A function invoked using Function.call

0 vrmOjc ={ 1 a ybet 0 2 syel :fnto( { aHlo ucin) 0 3 cnoelg'i M nm i '+ osl.o(H! y ae s ti.yae; hsmNm) 0 4 } , 0 5 0 6 mNm :'eec' yae Rbca 0 } 7 ; 0 8 0 vrscnOjc ={ 9 a eodbet
jqfundamentals.com/book/index.html#chapter-1 22/111

5/18/12

jQuery Fundamentals

1 0 mNm :'oi' yae Cln 1 } 1 ; 1 2 1 mOjc.aHlo) 3 ybetsyel(; / / lg 'i M nm i Rbca os H! y ae s eec' 1 mOjc.aHlocl(eodbet;/ 4 ybetsyel.alscnOjc) / lg 'i M nm i Cln os H! y ae s oi'
Example 2.42: A function created using Function.bind

0 vrmNm ='h goa ojc' 1 a yae te lbl bet, 0 2 0 3 syel =fnto ( { aHlo ucin ) 0 4 cnoelg'i M nm i '+ osl.o(H! y ae s ti.yae; hsmNm) 0 5 } , 0 6 0 7 mOjc ={ ybet 0 8 mNm :'eec' yae Rbca 0 9 } ; 1 0 1 vrmOjcHlo= 1 a ybetel syel.idmOjc) aHlobn(ybet; 1 2 1 syel(; 3 aHlo) / lg 'i M nm i / os H! y ae s tegoa ojc' h lbl bet 1 mOjcHlo) / lg 'i M nm i 4 ybetel(; / os H! y ae s Rbca eec'
Example 2.43: A function being attached to an object at runtime

0 vrmNm ='h goa ojc' 1 a yae te lbl bet, 0 2 0 3 syel =fnto( { aHlo ucin) 0 4 cnoelg'i M nm i '+ osl.o(H! y ae s ti.yae; hsmNm) 0 5 } , 0 6 0 7 mOjc ={ ybet 0 8 mNm :'eec' yae Rbca 0 9 } , 1 0 1 1 scnOjc ={ eodbet 1 2 mNm :'oi' yae Cln 1 3 } ; 1 4 1 mOjc.aHlo=syel; 5 ybetsyel aHlo 1 scnOjc.aHlo=syel; 6 eodbetsyel aHlo 1 7 1 syel(; 8 aHlo) / lg 'i M / os H! y nm i tegoa ojc' ae s h lbl bet 1 mOjc.aHlo) 9 ybetsyel(; / lg 'i M / os H! y nm i Rbca ae s eec' 2 scnOjc.aHlo) / lg 'i M 0 eodbetsyel(; / os H! y nm i Cln ae s oi'

Note
When invoking a function deep within a long namespace, it is often tempting to reduce the amount of code you need to
jqfundamentals.com/book/index.html#chapter-1 23/111

5/18/12

jQuery Fundamentals

type by storing a reference to the actual function as a single, shorter variable. It is important not to do this with instance methods as this will cause the value of t i within the hs function to change, leading to incorrect code operation. For instance: 0 vrmNmsae={ 1 a yaepc 0 2 mOjc :{ ybet 0 3 syel :fnto( { aHlo ucin) 0 4 cnoelg'i M nm i osl.o(H! y ae s '+ti.yae; hsmNm) 0 5 } , 0 6 0 7 mNm :'eec' yae Rbca 0 8 } 0 } 9 ; 1 0 1 vrhlo= 1 a el mNmsaemOjc.aHlo yaepc.ybetsyel; 1 2 1 hlo) / lg 'i M nm i 3 el(; / os H! y ae s udfnd neie' You can, however, safely reduce everything up to the object on which the method is invoked: 0 vrmNmsae={ 1 a yaepc 0 2 mOjc :{ ybet 0 3 syel :fnto( { aHlo ucin) 0 4 cnoelg'i M nm i osl.o(H! y ae s '+ti.yae; hsmNm) 0 5 } , 0 6 0 7 mNm :'eec' yae Rbca 0 8 } 0 } 9 ; 1 0 1 vroj=mNmsaemOjc; 1 a b yaepc.ybet 1 2 1 ojsyel(; / lg 'i M nm i 3 b.aHlo) / os H! y ae s Rbca eec'

Scope
"Scope" refers to the variables that are available to a piece of code at a given time. A lack of understanding of scope can lead to frustrating debugging experiences. When a variable is declared inside of a function using the v r a keyword, it is only available to code inside of that function code outside of that function cannot access the variable. On the other hand, functions defined inside that function will have access to to the declared variable. Furthermore, variables that are declared inside a function without the v rkeyword are not local to the function a
jqfundamentals.com/book/index.html#chapter-1 24/111

5/18/12

jQuery Fundamentals

JavaScript will traverse the scope chain all the way up to the window scope to find where the variable was previously defined. If the variable wasn't previously defined, it will be defined in the global scope, which can have extremely unexpected consequences;
Example 2.44: Functions have access to variables defined in the same scope

1 2 3 4 5 6 7 8

vrfo='el' a o hlo; vrsyel =fnto( { a aHlo ucin) cnoelgfo; osl.o(o) } ; syel(; aHlo) cnoelgfo; osl.o(o) / lg 'el' / os hlo / as lg 'el' / lo os hlo

Example 2.45: Code outside the scope in which a variable was defined does not have access to the variable

1 2 3 4 5 6 7

vrsyel =fnto( { a aHlo ucin) vrfo='el' a o hlo; cnoelgfo; osl.o(o) } ; syel(; aHlo) cnoelgfo; osl.o(o) / lg 'el' / os hlo / dentlgayhn / os' o ntig

Example 2.46: Variables with the same name can exist in different scopes with different values

1 2 3 4 5 6 7 8 9

vrfo='ol' a o wrd; vrsyel =fnto( { a aHlo ucin) vrfo='el' a o hlo; cnoelgfo; osl.o(o) } ; syel(; aHlo) cnoelgfo; osl.o(o) / lg 'el' / os hlo / lg 'ol' / os wrd

Example 2.47: Functions can "see" changes in variable values after the function is defined

0 vrmFnto =fnto( { 1 a yucin ucin) 0 2 vrfo='el' a o hlo; 0 3 0 4 vrmF =fnto( { a yn ucin) 0 5 cnoelgfo; osl.o(o) 0 6 } ; 0 7 0 8 fo='ol' o wrd; 0 9 1 0 rtr mF; eun yn 1 } 1 ; 1 2 1 vrf=mFnto(; 3 a yucin) 1 f) / lg 'ol'- u o 4 (; / os wrd - h h
jqfundamentals.com/book/index.html#chapter-1 25/111

5/18/12

jQuery Fundamentals

Example 2.48: Scope insanity

0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8

/ asl-xctn aoyosfnto / efeeuig nnmu ucin (ucin){ fnto( vrbz=1 a a ; vrbm=fnto( {aetbz;} a i ucin) lr(a) ; br=fnto( {aetbz;} a ucin) lr(a) ; }(; )) cnoelgbz; / bzi ntdfnd osl.o(a) / a s o eie otieo tefnto usd f h ucin

0 9 1 br) / bri dfndotieo te 0 a(; / a s eie usd f h aoyosfnto nnmu ucin 1 1 / bcuei ws' dcae wt / eas t ant elrd ih vr frhroe a; utemr, 1 2 / bcuei wsdfndi te / eas t a eie n h sm soea bz ae cp s a, 1 3 / i hsacs t bzee tog / t a ces o a vn huh ohrcd te oe 1 4 / otieo tefnto de nt / usd f h ucin os o 1 5 1 bm) / bmi ntdfndotieo 6 i(; / i s o eie usd f teaoyosfnto, h nnmu ucin 1 7 / s ti wl rsl i a err / o hs il eut n n ro

Closures
Closures are an extension of the concept of scope functions have access to variables that were available in the scope where the function was created. If thats confusing, dont worry: closures are generally best understood by example. In Functions can "see" changes in variable values after the function is defined, we saw how functions have access to changing variable values. The same sort of behavior exists with functions defined within loops the function "sees" the change in the variable's value even after the function is defined, resulting in all clicks alerting 5.
Example 2.49: How to lock in the value of i?

1 / ti wntbhv a w wn i t;* * hs o' eae s e at t o / 2 / eeycikwl aet5* * vr lc il lr / 3 fr(a i0 i5 i+ { o vr =; <; +) 4 $'pcik (<>lc m<p'.pedo'oy)cikfnto( e/>)apnT(bd'.lc(ucin) { 5 aeti; lr() 6 }; ) 7 }
Example 2.50: Locking in the value of i with a closure

1 / fx lstevleo iisd * i: coe h au f nie cetFnto,s i wntcag * raeucin o t o' hne / 2 vrcetFnto =fnto(){ a raeucin ucini 3 rtr fnto( {aeti;} eun ucin) lr() ; 4 } ; 5
jqfundamentals.com/book/index.html#chapter-1 26/111

5/18/12

jQuery Fundamentals

6 fr(a i0 i5 i+ { o vr =; <; +) 7 $'pcik (<>lc m<p'.pedo'oy)cikcetFnto(); e/>)apnT(bd'.lc(raeucini) 8 } Closures can also be used to resolve issues with the t i hs keyword, which is unique to each scope:
Example 2.51: Using a closure to access inner and outer object instances simultaneously

0 vrotrb ={ 1 a ueOj 0 2 mNm :'ue' yae otr, 0 3 otrucin:fnto ( { ueFnto ucin ) 0 4 0 5 / poiearfrnet otrb / rvd eeec o ueOj truhinrucinscoue hog neFnto' lsr 0 6 vrsl =ti; a ef hs 0 7 0 8 vrinrb ={ a neOj 0 9 mNm :'ne' yae inr, 1 0 inrucin:fnto ( { neFnto ucin ) 1 1 cnoelgsl.yae osl.o(efmNm, ti.yae;/ lg 'ue inr hsmNm) / os otr ne' 1 2 } 1 3 } ; 1 4 1 5 inrb.neFnto(; neOjinrucin) 1 6 1 7 cnoelgti.yae;/ lg osl.o(hsmNm) / os 'ue' otr 1 8 } 1 } 9 ; 2 0 2 otrb.ueFnto(; 1 ueOjotrucin) This mechanism can be particularly useful when dealing with callbacks, though in those cases, it is often better to use Function.bind, which will avoid any overhead associated with scope traversal.

Part II. jQuery: Basic Concepts


Back to top

jQuery Basics
jqfundamentals.com/book/index.html#chapter-1 27/111

5/18/12

jQuery Fundamentals

$(document).ready()
You cannot safely manipulate a page until the document is ready. jQuery detects this state of readiness for you; code included inside $ d c m n ) r a y )will only run once the page (ouet.ed( is ready for JavaScript code to execute.
Example 3.1: A $(document).ready() block

1 $dcmn)rayfnto( { (ouet.ed(ucin) 2 cnoelg'ed!) osl.o(ray'; 3 }; ) There is a shorthand for $ d c m n ) r a y )that you will (ouet.ed( sometimes see; however, I recommend against using it if you are writing code that people who aren't experienced with jQuery may see.
Example 3.2: Shorthand for $(document).ready()

1 $fnto( { (ucin) 2 cnoelg'ed!) osl.o(ray'; 3 }; ) You can also pass a named function to $ d c m n ) r a y ) (ouet.ed( instead of passing an anonymous function.
Example 3.3: Passing a named function instead of an anonymous function

1 fnto rayn){ ucin edF( 2 / cd t rnwe tedcmn i / oe o u hn h ouet s ray ed 3 } 4 5 6 $dcmn)rayrayn; (ouet.ed(edF)

Selecting Elements
The most basic concept of jQuery is to select some elements and do something with them. jQuery supports most CSS3 selectors, as well as some non-standard selectors. For a complete selector reference, visit http://api.jquery.com/category/selectors/. Following are a few examples of common selection techniques.
Example 3.4: Selecting elements by ID

1 $'mI';/ nt Isms b uiu pr (#yd) / oe D ut e nqe e pg ae


Example 3.5: Selecting elements by class name

jqfundamentals.com/book/index.html#chapter-1

28/111

5/18/12

jQuery Fundamentals

1 $'i.yls';/ promneipoe (dvmCas) / efrac mrvs i yuseiyeeettp f o pcf lmn ye


Example 3.6: Selecting elements by attribute

1 $'nu[aefrtnm]) / bwr, (iptnm=is_ae'; / eae ti cnb vr so hs a e ey lw


Example 3.7: Selecting elements by compound CSS selector

1 $'cnet u.epel'; (#otns lpol i)


Example 3.8: Pseudo-selectors

1 $'.xenlfrt) (aetra:is'; 2 $'rod) (t:d'; 3 $'mFr :nu'; / slc alipt (#yom ipt) / eet l nulk eeet i afr ie lmns n om 4 $'i:iil'; (dvvsbe) 5 $'i:t2'; (dvg()) frttredv is he is 6 $'i:nmtd) (dvaiae'; aiae dv nmtd is / alecp te / l xet h / alcrety / l urnl

Note
When you use the : i i l and : i d npseudo-selectors, vsbe hde jQuery tests the actual visibility of the element, not its CSS visibility or display that is, it looks to see if the element's physical height and width on the page are both greater than zero. However, this test doesn't work with < r elements; in this t> case, jQuery does check the CSS d s l yproperty, and ipa considers an element hidden if its d s l yproperty is set to ipa
n n . Elements oe

that have not been added to the DOM will always be considered hidden, even if the CSS that would affect them would render them visible. (See the Manipulation section later in this chapter to learn how to create and add elements to the DOM.) For reference, here is the code jQuery uses to determine whether an element is visible or hidden, with comments added for clarity: 0 jur.xrfleshde =fnto(ee 1 Qeyep.itr.idn ucin lm ){ 0 2 vrwdh=ee.fstit,hih = a it lmofeWdh egt ee.fstegt lmofeHih, 0 3 si =ee.oeaetLwrae) kp lmndNm.ooeCs( =="r; = t" 0 4 0 5 / de teeeethv 0hih,0 / os h lmn ae egt wdh it, 0 6 / adi' nta<r? / n ts o t> 0 7 rtr wdh==0& hih ==0& eun it = & egt = & !kp? si 0 8 0 9 / te i ms b hde / hn t ut e idn
jqfundamentals.com/book/index.html#chapter-1 29/111

5/18/12

jQuery Fundamentals

1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3

tu : re / bti i hswdhadhih / u f t a it n egt / adi' nta<r / n ts o t> wdh>0& hih >0& !kp? it & egt & si / te i ms b vsbe / hn t ut e iil fle: as hswdh a it <r, t> poet t rpry o / i w gthr,teeeet / f e e ee h lmn / adhih,bti' as a / n egt u ts lo / s cekisdsly / o hc t ipa / dcd wehri' hde / eie hte ts idn jur.uCSee,"ipa" QeycrS(lm dsly)

=="oe; = nn" 2 } 4 ; 2 5 2 jur.xrflesvsbe=fnto( 6 Qeyep.itr.iil ucin ee ){ lm 2 7 rtr !Qeyep.itr.idn eun jur.xrfleshde( ee ) lm ; 2 } 8 ; Choosing Selectors

Choosing good selectors is one way to improve the performance of your JavaScript. A little specificity for example, including an element type such as d vwhen selecting elements by class name i can go a long way. Generally, any time you can give jQuery a hint about where it might expect to find what you're looking for, you should. On the other hand, too much specificity can be a bad thing. A selector such as # y a l t e d t t . p c a is mTbe ha r hseil overkill if a selector such as # y a l t . p c a will get you mTbe hseil what you want. jQuery offers many attribute-based selectors, allowing you to make selections based on the content of arbitrary attributes using simplified regular expressions. 1 / fn al<> woerlatiue / id l as hs e trbt 2 / ed wt "hne" / ns ih tigr 3 $"[e$'hne'"; (arl=tigr]) While these can be useful in a pinch, they can also be extremely slow I once wrote an attribute-based selector that locked up my page for multiple seconds. Wherever possible, make your selections using IDs, class names, and tag names. Want to know more? Paul Irish has a great presentation about improving performance in JavaScript, with several slides focused specifically on selector performance.

Does My Selection Contain Any Elements?


Once you've made a selection, you'll often want to know whether
jqfundamentals.com/book/index.html#chapter-1 30/111

5/18/12

jQuery Fundamentals

you have anything to work with. You may be inclined to try something like: 1 i ((dvfo) {..} f $'i.o') . This won't work. When you make a selection using $ ) an object (, is always returned, and objects always evaluate to t u . Even if re your selection doesn't contain any elements, the code inside the i statement will still run. f Instead, you need to test the selection's length property, which tells you how many elements were selected. If the answer is 0, the length property will evaluate to false when used as a boolean value.
Example 3.9: Testing whether a selection contains elements

1 i ((dvfo)lnt){..} f $'i.o'.egh .

Saving Selections
Every time you make a selection, a lot of code runs, and jQuery doesn't do caching of selections for you. If you've made a selection that you might need to make again, you should save the selection in a variable rather than making the selection repeatedly.
Example 3.10: Storing selections in a variable

1 vr$is=$'i'; a dv (dv)

Note
In Storing selections in a variable, the variable name begins with a dollar sign. Unlike in other languages, there's nothing special about the dollar sign in JavaScript it's just another character. We use it here to indicate that the variable contains a jQuery object. This practice a sort of Hungarian notation is merely convention, and is not mandatory.

Once you've stored your selection, you can call jQuery methods on the variable you stored it in just like you would have called them on the original selection.

Note
A selection only fetches the elements that are on the page
jqfundamentals.com/book/index.html#chapter-1 31/111

5/18/12

jQuery Fundamentals

when you make the selection. If you add elements to the page later, you'll have to repeat the selection or otherwise add them to the selection stored in the variable. Stored selections don't magically update when the DOM changes.

Refining & Filtering Selections


Sometimes you have a selection that contains more than what you're after; in this case, you may want to refine your selection. jQuery offers several methods for zeroing in on exactly what you're after.
Example 3.11: Refining selections

1 $'i.o'.a(p) (dvfo)hs''; / dvfo / i.o eeet ta cnan<>s lmns ht oti p' 2 $'1)nt'br) (h'.o(.a'; / h / 1 eeet ta dnthv acaso br lmns ht o' ae ls f a 3 $'ll'.itr'cret) / (u i)fle(.urn'; / uodrdls ieswt caso cret nree it tm ih ls f urn 4 $'ll'.is(; (u i)frt) / js te / ut h frtuodrdls ie is nree it tm 5 $'ll'.q5; (u i)e() / te / h sxh it

Selecting Form Elements


jQuery offers several pseudo-selectors that help you find elements in your forms; these are especially helpful because it can be difficult to distinguish between form elements based on their state or type using standard CSS selectors. :button Selects < u t n elements and elements with bto>
tp=bto" ye"utn

:checkbox Selects inputs with t p = c e k o " ye"hcbx :checked Selects checked inputs :disabled Selects disabled form elements :enabled Selects enabled form elements :file
jqfundamentals.com/book/index.html#chapter-1 32/111

5/18/12

jQuery Fundamentals

Selects inputs with t p = f l " ye"ie :image Selects inputs with t p = i a e ye"mg" :input Selects < n u > < e t r a , and < e e t elements ipt, txae> slc> :password Selects inputs with t p = p s w r " ye"asod :radio Selects inputs with t p = r d o ye"ai" :reset Selects inputs with t p = r s t ye"ee" :selected Selects options that are selected :submit Selects inputs with t p = s b i " ye"umt :text Selects inputs with t p = t x " ye"et
Example 3.12: Using form-related pseduo-selectors

1 $'mFr :nu';/ gtaleeet (#yom ipt) / e l lmns ta acp ipt ht cet nu

Working with Selections


Once you have a selection, you can call methods on the selection. Methods generally come in two different flavors: getters and setters. Getters return a property of the first selected element; setters set a property on all selected elements.

Chaining
If you call a method on a selection and that method returns a jQuery object, you can continue to call jQuery methods on the object without pausing for a semicolon.
Example 3.13: Chaining

1 $'cnet)fn(h'.q2.tl'e (#otn'.id'3)e()hm(nw tx frtetidh!) et o h hr 3';


jqfundamentals.com/book/index.html#chapter-1 33/111

5/18/12

jQuery Fundamentals

If you are writing a chain that includes several steps, you (and the person who comes after you) may find your code more readable if you break the chain over several lines.
Example 3.14: Formatting chained code

1 $'cnet) (#otn' 2 .id'3) fn(h' 3 .q2 e() 4 .tl'e tx frtetidh!) hm(nw et o h hr 3'; If you change your selection in the midst of a chain, jQuery provides the $ f . n method to get you back to your original .ned selection.
Example 3.15: Restoring your original selection using $.fn.end

1 $'cnet) (#otn' 2 .id'3) fn(h' 3 .q2 e() 4 5 .tl'e tx frtetidh!) hm(nw et o h hr 3' .n( / rsoe teslcint al ed) / etrs h eeto o l h' i #otn 3s n cnet 6 .q0 e() 7 .tl'e tx frtefrt hm(nw et o h is h!) 3';

Note
Chaining is extraordinarily powerful, and it's a feature that many libraries have adapted since it was made popular by jQuery. However, it must be used with care. Extensive chaining can make code extremely difficult to modify or debug. There is no hard-and-fast rule to how long a chain should be just know that it is easy to get carried away.

Getters & Setters


jQuery overloads its methods, so the method used to set a value generally has the same name as the method used to get a value. When a method is used to set a value, it is called a setter. When a method is used to get (or read) a value, it is called a getter. Setters affect all elements in a selection; getters get the requested value only for the first element in the selection.
Example 3.16: The $.fn.html method used as a setter

1 $'1)hm(hlowrd) (h'.tl'el ol';


Example 3.17: The html method used as a getter

1 $'1)hm(; (h'.tl)
jqfundamentals.com/book/index.html#chapter-1 34/111

5/18/12

jQuery Fundamentals

Setters return a jQuery object, allowing you to continue to call jQuery methods on your selection; getters return whatever they were asked to get, meaning you cannot continue to call jQuery methods on the value returned by the getter.

CSS, Styling, & Dimensions


jQuery includes a handy way to get and set CSS properties of elements.

Note
CSS properties that normally include a hyphen need to be camel cased in JavaScript. For example, the CSS property f n - i eis expressed as f n S z when used as a otsz otie property name in JavaScript. This does not apply, however, when passing the name of a CSS property to the $ f . s .ncs method as a string in that case, either the camel cased or hyphenated form will work.

Example 3.18: Getting CSS properties

1 $'1)cs'otie) / rtrsa (h'.s(fnSz'; / eun srn sc a "9x tig uh s 1p" 2 $'1)cs'otsz';/ as wrs (h'.s(fn-ie) / lo ok
Example 3.19: Setting CSS properties

1 $'1)cs'otie,'0p';/ (h'.s(fnSz' 10x) / stiga idvda poet etn n niiul rpry 2 $'1)cs{'otie :'0p' 'oo' (h'.s( fnSz' 10x, clr :'e'};/ stigmlil poete rd ) / etn utpe rpris Note the style of the argument we use on the second line it is an object that contains multiple properties. This is a common way to pass multiple arguments to a function, and many jQuery setter methods accept objects to set mulitple values at once.

Using CSS Classes for Styling


As a getter, the $ f . s method is valuable; however, it should .ncs generally be avoided as a setter in production-ready code, because you don't want presentational information in your JavaScript. Instead, write CSS rules for classes that describe the various visual states, and then simply change the class on the element you want to affect.
Example 3.20: Working with classes

jqfundamentals.com/book/index.html#chapter-1

35/111

5/18/12

jQuery Fundamentals

1 2 3 4 5 6 7

vr$1=$'1) a h (h'; $1adls(bg) h.dCas'i'; $1rmvCas'i'; h.eoels(bg) $1tglCas'i'; h.ogels(bg) i (h.aCas'i'){..} f $1hsls(bg) .

Classes can also be useful for storing state information about an element, such as indicating that an element is selected.

Dimensions
jQuery offers a variety of methods for obtaining and modifying dimension and position information about an element. The code in Basic dimensions methods, is just a very brief overview of the dimensions functionality in jQuery; for complete details about jQuery dimension methods, visit http://api.jquery.com/category/dimensions/.
Example 3.21: Basic dimensions methods

1 $'1)wdh'0x) (h'.it(5p'; / st tewdh / es h it o alH eeet f l 1 lmns 2 $'1)wdh) (h'.it(; / gt tewdh / es h it o tefrtH f h is 1 3 4 $'1)hih(5p'; / st tehih (h'.egt'0x) / es h egt o alH eeet f l 1 lmns 5 $'1)hih(; (h'.egt) / gt tehih / es h egt o tefrtH f h is 1 6 7 $'1)psto(; (h'.oiin) / rtrsa / eun n ojc cnann psto bet otiig oiin 8 / ifrainfr / nomto o tefrtH rltv t h is 1 eaie o 9 / is"fst / t ofe (oiind prn" pstoe) aet

Attributes
An element's attributes can contain useful information for your application, so it's important to be able to get and set them. The $ f . t rmethod acts as both a getter and a setter. As .nat with the $ f . s method, $ f . t ras a setter can accept .ncs .nat either a key and a value, or an object containing one or more key/value pairs.
Example 3.22: Setting attributes

1 $''.tr'rf, (a)at(he' 'lMHesrTeaeo.tl) alyrfAehSmNwhm'; 2 $''.tr{ (a)at( 3 'il':'l tte aetesm tte al ils r h ae to' o!, 4 'rf :'oehnNwhm' he' smtige.tl 5 }; )
jqfundamentals.com/book/index.html#chapter-1 36/111

5/18/12

jQuery Fundamentals

This time, we broke the object up into multiple lines. Remember, whitespace doesn't matter in JavaScript, so you should feel free to use it liberally to make your code more legible! You can use a minification tool later to strip out unnecessary whitespace for production.
Example 3.23: Getting attributes

1 $''.tr'rf) / rtrstehe (a)at(he'; / eun h rf frtefrtaeeeti tedcmn o h is lmn n h ouet

Traversing
Once you have a jQuery selection, you can find other elements using your selection as a starting point. For complete documentation of jQuery traversal methods, visit http://api.jquery.com/category/traversing/.

Note
Be cautious with traversing long distances in your documents complex traversal makes it imperative that your document's structure remain the same, something that's difficult to guarantee even if you're the one creating the whole application from server to client. One- or two-step traversal is fine, but you generally want to avoid traversals that take you from one container to another.

Example 3.24: Moving around the DOM using traversal methods

1 2 3 4 5

$'1)nx(p) (h'.et''; $'i:iil'.aet) (dvvsbe)prn(; $'nu[aefrtnm])coet'om) (iptnm=is_ae'.lss(fr'; $'mLs'.hlrn) (#yit)cide(; $'islce'.ilns) (l.eetd)sbig(;

You can also iterate over a selection using $ f . a h This .nec. method iterates over all of the elements in a selection, and runs a function for each one. The function receives the index of the current element and the DOM element itself as arguments. Inside the function, the DOM element is also available as t i by hs default.
Example 3.25: Iterating over a selection

1 $'mLs l'.ahfnto(d,e){ (#yit i)ec(ucinix l 2 cnoelg osl.o( 3 'lmn '+ix+ Eeet d 4 'a tefloighm:'+ hs h olwn tl 5 $e)hm( (l.tl)
jqfundamentals.com/book/index.html#chapter-1 37/111

5/18/12

jQuery Fundamentals

7 ) ; 6 };)

Manipulating Elements
Once you've made a selection, the fun begins. You can change, move, remove, and clone elements. You can also create new elements via a simple syntax. For complete documentation of jQuery manipulation methods, visit http://api.jquery.com/category/manipulation/.

Getting and Setting Information about Elements


There are any number of ways you can change an existing element. Among the most common tasks you'll perform is changing the inner HTML or attribute of an element. jQuery offers simple, cross-browser methods for these sorts of manipulations. You can also get information about elements using many of the same methods in their getter incarnations. We'll see examples of these throughout this section, but specifically, here are a few methods you can use to get and set information about elements.

Note
Changing things about elements is trivial, but remember that the change will affect all elements in the selection, so if you just want to change one element, be sure to specify that in your selection before calling a setter method.

Note
When methods act as getters, they generally only work on the first element in the selection, and they do not return a jQuery object, so you can't chain additional methods to them. One notable exception is $ f . e t as mentioned .ntx; below, it gets the text for all elements in the selection.

$.fn.html Get or set the html contents. $.fn.text Get or set the text contents; HTML will be stripped. $.fn.attr
jqfundamentals.com/book/index.html#chapter-1 38/111

5/18/12

jQuery Fundamentals

Get or set the value of the provided attribute. $.fn.width Get or set the width in pixels of the first element in the selection as an integer. $.fn.height Get or set the height in pixels of the first element in the selection as an integer. $.fn.position Get an object with position information for the first element in the selection, relative to its first positioned ancestor. This is a getter only. $.fn.val Get or set the value of form elements.
Example 3.26: Changing the HTML of an element

1 $'mDvpfrt) (#yi :is' 2 .tl'e <togfrt/tog hm(Nw srn>is<srn> prgah'; aarp!)

Moving, Copying, and Removing Elements


There are a variety of ways to move elements around the DOM; generally, there are two approaches: Place the selected element(s) relative to another element Place an element relative to the selected element(s) For example, jQuery provides $ f . n e t f e and .nisrAtr
$ f . f e . The $ f . n e t f e method places .natr .nisrAtr

the selected element(s) after the element that you provide as an argument; the $ f . f e method places the element provided as an .natr argument after the selected element. Several other methods follow this pattern: $ f . n e t e o eand $ f . e o e .nisrBfr .nbfr; $ f . p e d oand $ f . p e d and $ f . r p n T and .napnT .napn; .npeedo
$f.rpn. .npeed

The method that makes the most sense for you will depend on what elements you already have selected, and whether you will need to store a reference to the elements you're adding to the page. If you need to store a reference, you will always want to take the first approach placing the selected elements relative to another element as it returns the element(s) you're placing. In this case, $ f . n e t f e , $ f . n e t e o e .nisrAtr .nisrBfr, $ f . p e d o and $ f . r p n T will be your tools of choice. .napnT, .npeedo
jqfundamentals.com/book/index.html#chapter-1 39/111

5/18/12

jQuery Fundamentals

Example 3.27: Moving elements using different approaches

1 / mk tefrtls ie tels ls / ae h is it tm h at it ie tm 2 vr$i=$'mLs a l (#yit l:is'.pedo'mLs'; ifrt)apnT(#yit) 3 4 / aohrapoc t tesm polm / nte prah o h ae rbe 5 $'mLs'.ped$'mLs l:is') (#yit)apn((#yit ifrt); 6 7 / nt ta teesn wyt acs te / oe ht hr' o a o ces h 8 / ls ie ta w mvd a ti rtrs / it tm ht e oe, s hs eun 9 / tels isl / h it tef Cloning Elements When you use methods such as $.fn.appendTo, you are moving the element; sometimes you want to make a copy of the element instead. In this case, you'll need to use $.fn.clone first.
Example 3.28: Making a copy of an element

1 / cp tefrtls ie t teedo / oy h is it tm o h n f tels h it 2 $'mLs (#yit l:is'.ln(.pedo'mLs'; ifrt)coe)apnT(#yit)

Note
If you need to copy related data and events, be sure to pass t u as an argument to $ f . l n . re .ncoe

Removing Elements There are two ways to remove elements from the page: $ f . e o eand $ f . e a h You'll use $ f . e o ewhen you .nrmv .ndtc. .nrmv want to permanently remove the selection from the page; while the method does return the removed element(s), those elements will not have their associated data and events attached to them if you return them to the page. If you need the data and events to persist, you'll want to use $ f . e a hinstead. Like $ f . e o e it returns the selection, .ndtc .nrmv, but it also maintains the data and events associated with the selection, so you can restore the selection to the page at a later time.

Note
The $ f . e a hmethod is extremely valuable if you are .ndtc
jqfundamentals.com/book/index.html#chapter-1 40/111

5/18/12

jQuery Fundamentals

doing heavy manipulation to an element. In that case, it's beneficial to $ f . e a hthe element from the page, work .ndtc on it in your code, and then restore it to the page when you're done. This saves you from expensive "DOM touches" while maintaining the element's data and events.

If you want to leave the element on the page but simply want to remove its contents, you can use $ f . m t to dispose of the .nepy element's inner HTML.

Creating New Elements


jQuery offers a trivial and elegant way to create new elements using the same $ )method you use to make selections. (
Example 3.29: Creating new elements

1 $'pTi i anwprgah/>) (<>hs s e aarp<p'; 2 $'l cas"e"nwls ie<l>) (<i ls=nw>e it tm/i';
Example 3.30: Creating a new element with an attribute object

1 $'a>,{ (</' 2 hm :'hsi a<tognw/tog tl Ti s srn>e<srn> ln' ik, 3 'ls':'e' cas nw, 4 he :'o.tl rf fohm' 5 }; ) Note that in the attributes object we included as the second argument, the property name class is quoted, while the property names text and href are not. Property names generally do not need to be quoted unless they are reserved words (as class is in this case). When you create a new element, it is not immediately added to the page. There are several ways to add an element to the page once it's been created.
Example 3.31: Getting a new element on to the page

1 vr$yeEeet=$'pNw a mNwlmn (<>e eeet/>) lmn<p'; 2 $yeEeetapnT(#otn'; mNwlmn.pedo'cnet) 3 4 $yeEeetisrAtr'lls';/ mNwlmn.netfe(u:at) / ti wl rmv tepfo #otn! hs il eoe h rm cnet 5 $'l)ls(.fe(mNwlmn.ln() (u'.at)atr$yeEeetcoe); / coeteps nww hv 2 / ln h o o e ae Strictly speaking, you don't have to store the created element in a variable you could just call the method to add the element to the page directly after the $(). However, most of the time you will want a reference to the element you added, so
jqfundamentals.com/book/index.html#chapter-1 41/111

5/18/12

jQuery Fundamentals

you don't need to select it later. You can even create an element as you're adding it to the page, but note that in this case you don't get a reference to the newly created element.
Example 3.32: Creating and adding an element to the page at the same time

1 $'l)apn(<ils ie<l>) (u'.ped'l>it tm/i';

Note
The syntax for adding new elements to the page is so easy, it's tempting to forget that there's a huge performance cost for adding to the DOM repeatedly. If you are adding many elements to the same container, you'll want to concatenate all the html into a single string, and then append that string to the container instead of appending the elements one at a time. You can use an array to gather all the pieces together, then j i them into a single string for appending. on 1 vrmIes=[,$yit= a ytm ] mLs $'mLs'; (#yit) 2 3 fr(a i0 i10 i+ { o vr =; <0; +) 4 mIesps(<iie '+i+ ytm.uh'l>tm '/i'; <l>) 5 } 6 7 $yitapn(ytm.on'); mLs.pedmIesji(')

Manipulating Attributes
jQuery's attribute manipulation capabilities are extensive. Basic changes are simple, but the $.fn.attr method also allows for more complex manipulations. It can either set an explicit value, or set a value using the return value of a function. When the function syntax is used, the function receives two arguments: the zerobased index of the element whose attribute is being changed, and the current value of the attribute being changed.
Example 3.33: Manipulating a single attribute

1 $'mDvafrt)at(he' (#yi :is'.tr'rf, 'eDsiainhm'; nwetnto.tl)


Example 3.34: Manipulating multiple attributes

1 $'mDvafrt)at( (#yi :is'.tr{ 2 he :'eDsiainhm' rf nwetnto.tl, 3 rl:'ue-pca' e sprseil


jqfundamentals.com/book/index.html#chapter-1 42/111

5/18/12

jQuery Fundamentals

4 }; )
Example 3.35: Using a function to determine an attribute's new value

0 $'mDvafrt)at( 1 (#yi :is'.tr{ 0 2 rl:'ue-pca' e sprseil, 0 3 he :fnto(d,he){ rf ucinix rf 0 4 rtr 'nw'+he; eun /e/ rf 0 5 } 0 }; 6 ) 0 7 0 $'mDvafrt)at(he' 8 (#yi :is'.tr'rf, fnto(d,he){ ucinix rf 0 9 rtr 'nw'+he; eun /e/ rf 1 }; 0 )

Exercises
Selecting
Open the file / x r i e / n e . t lin your browser. Use the eecssidxhm file / x r i e / s s n b x j or work in Firebug to accomplish eecssj/ado.s the following: 1. Select all of the div elements that have a class of "module". 2. Come up with three selectors that you could use to get the third item in the #myList unordered list. Which is the best to use? Why? 3. Select the label for the search input using an attribute selector. 4. Figure out how many elements on the page are hidden (hint: .length). 5. Figure out how many image elements on the page have an alt attribute. 6. Select all of the odd table rows in the table body.

Traversing
Open the file / x r i e / n e . t lin your browser. Use the eecssidxhm file / x r i e / s s n b x j or work in Firebug to accomplish eecssj/ado.s the following: 1. Select all of the image elements on the page; log each image's alt attribute. 2. Select the search input text box, then traverse up to the form and add a class to the form. 3. Select the list item inside #myList that has a class of "current" and remove that class from it; add a class of "current" to the next list item.
jqfundamentals.com/book/index.html#chapter-1 43/111

5/18/12

jQuery Fundamentals

4. Select the select element inside #specials; traverse your way to the submit button. 5. Select the first list item in the #slideshow element; add the class "current" to it, and then add a class of "disabled" to its sibling elements.

Manipulating
Open the file / x r i e / n e . t lin your browser. Use the eecssidxhm file / x r i e / s s n b x j or work in Firebug to accomplish eecssj/ado.s the following: 1. Add five new list items to the end of the unordered list #myList. Hint: 1 fr(a i=0 i5 i+ {..} o vr ; <; +) . 2. Remove the odd list items 3. Add another h2 and another paragraph to the last div.module 4. Add another option to the select element; give the option the value "Wednesday" 5. Add a new div.module to the page after the last one; put a copy of one of the existing images inside of it.

Back to top

jQuery Core
$vs $ ) (
Until now, weve been dealing entirely with methods that are called on a jQuery object. For example: 1 $'1)rmv(; (h'.eoe) Most jQuery methods are called on jQuery objects as shown above; these methods are said to be part of the $ f namespace, .n or the jQuery prototype, and are best thought of as jQuery object methods. However, there are several methods that do not act on a selection; these methods are said to be part of the jQuery
jqfundamentals.com/book/index.html#chapter-1 44/111

5/18/12

jQuery Fundamentals

namespace, and are best thought of as core jQuery methods. This distinction can be incredibly confusing to new jQuery users. Heres what you need to remember: Methods called on jQuery selections are in the $ f .n namespace, and automatically receive and return the selection as this. Methods in the $namespace are generally utility-type methods, and do not work with selections; they are not automatically passed any arguments, and their return value will vary. There are a few cases where object methods and core methods have the same names, such as $ e c and $ f . a h In these .ah .nec. cases, be extremely careful when reading the documentation that you are exploring the correct method.

Utility Methods
jQuery offers several utility methods in the $namespace. These methods are helpful for accomplishing routine programming tasks. Below are examples of a few of the utility methods; for a complete reference on jQuery utility methods, visit http://api.jquery.com/category/utilities/. $.trim Removes leading and trailing whitespace. 1 $ti( .rm' lt o etawiepc os f xr htsae '; ) 2 / rtrs'oso etawiepc' / eun lt f xr htsae $.each Iterates over arrays and objects. 1 $ec( 'o' 'a' 'a'] .ah[ fo, br, bz , fnto(d,vl { ucinix a) 2 cnoelg'lmn '+ix+'s osl.o(eeet d i '+vl; a) 3 }; ) 4 5 $ec( fo:'a' bz:'i'} .ah{ o br, a bm , fnto(,v { ucink ) 6 cnoelgk+':'+v; osl.o( ) 7 }; )

Note
There is also a method $ f . a h which is used for .nec, iterating over a selection of elements.

jqfundamentals.com/book/index.html#chapter-1

45/111

5/18/12

jQuery Fundamentals

$.inArray Returns a value's index in an array, or -1 if the value is not in the array. 1 vrmAry=[1 2 3 5] a yra , , , ; 2 3 i (.nra(,mAry !=-){ f $iAry4 yra) = 1 4 cnoelg'on i!) osl.o(fud t'; 5 } $.extend Changes the properties of the first object using the properties of subsequent objects. 1 vrfrtbet={fo:'a' a: a isOjc o br, ''} b ; 2 vrscnOjc ={fo:'a'} a eodbet o bz ; 3 4 vrnwbet=$etn(isOjc, a eOjc .xedfrtbet scnOjc) eodbet; 5 cnoelgfrtbetfo;/ 'a' osl.o(isOjc.o) / bz 6 cnoelgnwbetfo; / 'a' osl.o(eOjc.o) / bz If you don't want to change any of the objects you pass to $ e t n , pass an empty object as the first argument. .xed 1 vrfrtbet={fo:'a' a: a isOjc o br, ''} b ; 2 vrscnOjc ={fo:'a'} a eodbet o bz ; 3 4 vrnwbet=$etn(} a eOjc .xed{, frtbet scnOjc) isOjc, eodbet; 5 cnoelgfrtbetfo;/ 'a' osl.o(isOjc.o) / br 6 cnoelgnwbetfo; / 'a' osl.o(eOjc.o) / bz $.proxy Returns a function that will always run in the provided scope that is, sets the meaning of t i inside the passed hs function to the second argument. 1 vrmFnto =fnto( { a yucin ucin) cnoelgti) } osl.o(hs; ; 2 vrmOjc ={fo:'a'} a ybet o br ; 3 4 mFnto(;/ lg wno ojc yucin) / os idw bet 5 6 vrmPoyucin= a yrxFnto $poymFnto,mOjc) .rx(yucin ybet; 7 mPoyucin) / lg mOjc yrxFnto(; / os ybet ojc bet If you have an object with methods, you can pass the object and the name of a method to return a function that will always run in the scope of the object. 1 vrmOjc ={ a ybet 2 mF :fnto( { yn ucin) 3 cnoelgti) osl.o(hs;
jqfundamentals.com/book/index.html#chapter-1 46/111

5/18/12

jQuery Fundamentals

4 } 5 } ; 6 7 $'fo)cikmOjc.yn;/ lg (#o'.lc(ybetmF) / os DMeeet#o O lmn fo 8 $'fo)cik$poymOjc, (#o'.lc(.rx(ybet 'yn);/ lg mOjc mF') / os ybet

Checking types
As mentioned in the "JavaScript basics" section, jQuery offers a few basic utility methods for determining the type of a specific value.
Example 4.1: Checking the type of an arbitrary value

0 vrmVle=[,2 3; 1 a yau 1 , ] 0 2 0 / UigJvSrp' tpo oeao t 3 / sn aacits yef prtr o ts frpiaietps et o rmtv ye 0 tpo mVle= 'tig;/ fle 4 yef yau = srn' / as 0 tpo mVle= 'ubr;/ fle 5 yef yau = nme' / as 0 tpo mVle= 'neie' / fle 6 yef yau = udfnd; / as 0 tpo mVle= 'ola' / fle 7 yef yau = boen; / as 0 8 0 / Uigsrc eult oeao t cek 9 / sn tit qaiy prtr o hc frnl o ul 1 mVle==nl;/ fle 0 yau = ul / as 1 1 1 / Uigjur' mtost cekfrnn 2 / sn Qeys ehd o hc o opiaietps rmtv ye 1 jur.sucinmVle;/ fle 3 QeyiFnto(yau) / as 1 jur.sliOjc(yau) / fle 4 QeyiPanbetmVle; / as 1 jur.sra(yau) / tu 5 QeyiArymVle; / re

Data Methods
As your work with jQuery progresses, you'll find that there's often data about an element that you want to store with the element. In plain JavaScript, you might do this by adding a property to the DOM element, but you'd have to deal with memory leaks in some browsers. jQuery offers a straightforward way to store data related to an element, and it manages the memory issues for you.
Example 4.2: Storing and retrieving data related to an element

1 $'mDv)dt(kyae,{fo:'a' (#yi'.aa'eNm' o br }; ) 2 $'mDv)dt(kyae) / {fo: (#yi'.aa'eNm'; / o 'a'} br You can store any kind of data on an element, and it's hard to overstate the importance of this when you get into complex application development. For the purposes of this class, we'll mostly use $ f . a ato store references to other elements. .ndt

jqfundamentals.com/book/index.html#chapter-1

47/111

5/18/12

jQuery Fundamentals

For example, we may want to establish a relationship between a list item and a div that's inside of it. We could establish this relationship every single time we interact with the list item, but a better solution would be to establish the relationship once, and then store a pointer to the div on the list item using $ f . a a .ndt:
Example 4.3: Storing a relationship between elements using $.fn.data

1 $'mLs l'.ahfnto( { (#yit i)ec(ucin) 2 vr$i=$ti) $i = a l (hs, dv $ifn(dvcnet) l.id'i.otn'; 3 $idt(cneti' $i) l.aa'otnDv, dv; 4 }; ) 5 6 / ltr w dnthv t fn tedv / ae, e o' ae o id h i aan gi; 7 / w cnjs ra i fo tels ie' / e a ut ed t rm h it tms dt aa 8 vr$isL =$'mLs l:is'; a frti (#yit ifrt) 9 $isL.aa'otnDv)hm(nw frtidt(cneti'.tl'e cnet) otn'; In addition to passing $ f . a aa single key-value pair to store .ndt data, you can also pass an object containing one or more pairs.

Feature & Browser Detection


Although jQuery eliminates most JavaScript browser quirks, there are still occasions when your code needs to know about the browser environment. jQuery offers the $ s p o tobject, as well as the deprecated .upr $ b o s robject, for this purpose. For complete documentation .rwe on these objects, visit http://api.jquery.com/jQuery.support/ and http://api.jquery.com/jQuery.browser/. The $ s p o tobject is dedicated to determining what features .upr a browser supports; it is recommended as a more future-proof method of customizing your JavaScript for different browser environments. The $ b o s robject was deprecated in favor of the $ s p o t .rwe .upr object, but it will not be removed from jQuery anytime soon. It provides direct detection of the browser brand and version.

Avoiding Conflicts with Other Libraries


If you are using another JavaScript library that uses the $ variable, you can run into conflicts with jQuery. In order to avoid these conflicts, you need to put jQuery in no-conflict mode immediately after it is loaded onto the page and before you attempt to use jQuery in your page. When you put jQuery into no-conflict mode, you have the option
jqfundamentals.com/book/index.html#chapter-1 48/111

5/18/12

jQuery Fundamentals

of assigning a variable name to replace $ .


Example 4.4: Putting jQuery into no-conflict mode

1 <citsc"rttp.s>/cit srp r=pooyej"<srp> 2 <citsc"qeyj"<srp> srp r=jur.s>/cit 3 <citvr$ =jur.oofit) srp>a j QeynCnlc(; <srp> /cit You can continue to use the standard $by wrapping your code in a self-executing anonymous function; this is a standard pattern for plugin authoring, where the author cannot know whether another library will have taken over the $ .
Example 4.5: Using the $ inside a self-executing anonymous function

1 2 3 4 5 6 7 8 9

<citsc"rttp.s>/cit srp r=pooyej"<srp> <citsc"qeyj"<srp> srp r=jur.s>/cit <cit srp> jur.oofit) QeynCnlc(; (ucin$ { fnto() / yu cd hr,uigte$ / or oe ee sn h }(Qey; )jur) <srp> /cit

Back to top

Events
Overview
jQuery provides simple methods for attaching event handlers to selections. When an event occurs, the provided function is executed. Inside the function, this refers to the element that was clicked. For details on jQuery events, visit http://api.jquery.com/category/events/. The event handling function can receive an event object. This object can be used to determine the nature of the event, and to prevent the events default behavior. For details on the event object, visit http://api.jquery.com/category/events/event-object/.

Connecting Events to Elements


jqfundamentals.com/book/index.html#chapter-1 49/111

5/18/12

jQuery Fundamentals

jQuery offers convenience methods for most common events, and these are the methods you will see used most often. These methods including $ f . l c , $ f . o u , $ f . l r .ncik .nfcs .nbu, $ f . h n e etc. are shorthand for jQuery's $ f . i d .ncag, .nbn method. The bind method is useful for binding the same handler function to multiple events, when you want to provide data to the event hander, when you are working with custom events, or when you want to pass an object of multiple events and handlers.
Example 5.1: Event binding using a convenience method

1 $''.lc(ucin){ (p)cikfnto( 2 cnoelg'lc'; osl.o(cik) 3 }; )


Example 5.2: Event biding using the $.fn.bind method

1 $''.id'lc' fnto( { (p)bn(cik, ucin) 2 cnoelg'lc'; osl.o(cik) 3 }; )


Example 5.3: Event binding using the $.fn.bind method with data

1 $'nu'.id (ipt)bn( 2 'lc cag' / bn t mlil cik hne, / id o utpe eet vns 3 {fo:'a'} / ps i dt o br , / as n aa 4 5 fnto(vnOjc){ ucineetbet 6 cnoelgeetbettp, osl.o(vnOjc.ye eetbetdt) vnOjc.aa; 7 / lg eettp,te {fo: / os vn ye hn o 'a'} br 8 } 9 ) ;

Connecting Events to Run Only Once


Sometimes you need a particular handler to run only once after that, you may want no handler to run, or you may want a different handler to run. jQuery provides the $ f . n method .noe for this purpose.
Example 5.4: Switching handlers using the $.fn.one method

1 $''.n(cik,fnto( { (p)oe'lc' ucin) 2 cnoelg'o js cikdti fr osl.o(Yu ut lce hs o tefrttm!) h is ie'; 3 $ti)cikfnto( { (hs.lc(ucin) cnoelg'o hv cikdti osl.o(Yu ae lce hs bfr!) }; eoe'; ) 4 }; ) The $ f . n method is especially useful if you need to do some .noe complicated setup the first time an element is clicked, but not subsequent times.
jqfundamentals.com/book/index.html#chapter-1 50/111

5/18/12

jQuery Fundamentals

Disconnecting Events
To disconnect an event handler, you use the $ f . n i d .nubn method and pass in the event type to unbind. If you attached a named function to the event, then you can isolate the unbinding to that named function by passing it as the second argument.
Example 5.5: Unbinding all click handlers on a selection

1 $''.nid'lc'; (p)ubn(cik)
Example 5.6: Unbinding a particular click handler

1 vrfo=fnto( {cnoelg'o'; a o ucin) osl.o(fo) } ; 2 vrbr=fnto( {cnoelg'a'; a a ucin) osl.o(br) } ; 3 4 $''.id'lc' fo.id'lc' (p)bn(cik, o)bn(cik, br; a) 5 $''.nid'lc' br;/ foi (p)ubn(cik, a) / o s silbudt tecikeet tl on o h lc vn

Namespacing Events
For complex applications and for plugins you share with others, it can be useful to namespace your events so you don't unintentionally disconnect events that you didn't or couldn't know about.
Example 5.7: Namespacing events

1 $''.id'lc.yaepc' fnto( (p)bn(cikmNmsae, ucin) {/ ..* }; * . / ) 2 $''.nid'lc.yaepc'; (p)ubn(cikmNmsae) 3 $''.nid'mNmsae) / ubn (p)ubn(.yaepc'; / nid aleet i tenmsae l vns n h aepc

Binding Multiple Events


Quite often elements in your application will be bound to multiple events, each having a different function for handing the event. In these cases you can pass an object into $ f . i dwith .nbn one or more key/value pairs, with the key being the event name and the value being the function to handle the event.
Example 5.8: Binding Multiple Events

1 $''.id{ (p)bn( 2 'lc' fnto( { cik: ucin) cnoelg'lce!) } osl.o(cikd'; , 3 'osoe' fnto( { muevr: ucin) cnoelg'oee!) } osl.o(hvrd'; 4 }; )

jqfundamentals.com/book/index.html#chapter-1

51/111

5/18/12

jQuery Fundamentals

Note
The option to pass an object of multiple events and handlers to $ f . i dwas introduced in jQuery 1.4.4. .nbn

Inside the Event Handling Function


As mentioned in the overview, the event handling function receives an event object, which contains many properties and methods. The event object is most commonly used to prevent the default action of the event via the preventDefault method. However, the event object contains a number of other useful properties and methods, including: pageX, pageY The mouse position at the time the event occurred, relative to the top left of the page. type The type of the event (e.g. "click"). which The button or key that was pressed. data Any data that was passed in when the event was bound. target The DOM element that initiated the event. preventDefault() Prevent the default action of the event (e.g. following a link). stopPropagation() Stop the event from bubbling up to other elements. In addition to the event object, the event handling function also has access to the DOM element that the handler was bound to via the keyword t i . To turn the DOM element into a jQuery hs object that we can use jQuery methods on, we simply do $ t i ) often following this idiom: (hs,
jqfundamentals.com/book/index.html#chapter-1 52/111

5/18/12

jQuery Fundamentals

1 vr$hs=$ti) a ti (hs;
Preventing a link from being followed

1 $''.lc(ucine { (a)cikfnto() 2 vr$hs=$ti) a ti (hs; 3 i (ti.tr'rf)mth'vl) { f $hsat(he'.ac(ei') 4 epeeteal(; .rvnDfut) 5 $hsadls(ei'; ti.dCas'vl) 6 } 7 }; )

Triggering Event Handlers


jQuery provides a way to trigger the event handlers bound to an element without any user interaction via the $ f . r g e .ntigr method. While this method has its uses, it should not be used simply to call a function that was bound as a click handler. Instead, you should store the function you want to call in a variable, and pass the variable name when you do your binding. Then, you can call the function itself whenever you want, without the need for $ f . r g e . .ntigr
Triggering an event handler the right way

0 vrfo=fnto(){ 1 a o ucine 0 2 i (){ f e 0 3 cnoelge; osl.o() 0 4 }es { le 0 5 cnoelg'hsdd\tcm fo osl.o(ti in' oe rm a eet'; n vn!) 0 6 } 0 } 7 ; 0 8 0 9 1 $''.lc(o) 0 (p)cikfo; 1 1 1 fo) / isedo 2 o(; / nta f $''.rge(cik) (p)tigr'lc'

Increasing Performance with Event Delegation


You'll frequently use jQuery to add new elements to the page, and when you do, you may need to bind events to those new elements events you already bound to similar elements that were on the page originally. Instead of repeating your event binding every time you add elements to the page, you can use event delegation. With event delegation, you bind your event to a container element, and then when the event occurs, you look to see which contained element it occurred on. If this sounds complicated, luckily jQuery makes it easy with its $ f . i eand .nlv
$ f . e e a emethods. .ndlgt

While most people discover event delegation while dealing with


jqfundamentals.com/book/index.html#chapter-1 53/111

5/18/12

jQuery Fundamentals

elements added to the page later, it has some performance benefits even if you never add more elements to the page. The time required to bind event handlers to hundreds of individual elements is non-trivial; if you have a large set of elements, you should consider delegating related events to a container element.

Note
The $ f . i emethod was introduced in jQuery 1.3, and at .nlv that time only certain event types were supported. As of jQuery 1.4.2, the $ f . e e a emethod is available, and is .ndlgt the preferred method.

Event delegation using $ f . e e a e .ndlgt

1 $'mUodrdit)dlgt(l' (#ynreeLs'.eeae'i, 'lc' fnto(){ cik, ucine 2 vr$yittm=$ti) a mLsIe (hs; 3 / .. / . 4 }; )


Event delegation using $ f . i e .nlv

1 $'mUodrditl'.ie'lc' (#ynreeLs i)lv(cik, fnto(){ ucine 2 vr$yittm=$ti) a mLsIe (hs; 3 / .. / . 4 }; )

Unbinding Delegated Events


If you need to remove delegated events, you can't simply unbind them. Instead, use $ f . n e e a efor events connected with .nudlgt
$ f . e e a e and $ f . i for .ndlgt, .nde

events connected with $ f . i e As with bind, you can optionally pass in the name of .nlv. the bound function.
Unbinding delegated events

1 $'mUodrdit)udlgt(l' (#ynreeLs'.neeae'i, 'lc'; cik) 2 $'mUodrditl'.i(cik) (#ynreeLs i)de'lc';

Event Helpers
jQuery offers two event-related helper functions that save you a few keystrokes.
$f.oe .nhvr

The $ f . o e method lets you pass one or two functions to be .nhvr


jqfundamentals.com/book/index.html#chapter-1 54/111

5/18/12

jQuery Fundamentals

run when the m u e n e and m u e e v events occur on an osetr oslae element. If you pass one function, it will be run for both events; if you pass two functions, the first will run for m u e n e , and osetr the second will run for m u e e v . oslae

Note
Prior to jQuery 1.4, the $ f . o e method required two .nhvr functions.

The hover helper function

1 $'mn l'.oe(ucin){ (#eu i)hvrfnto( 2 $ti)tglCas'oe'; (hs.ogels(hvr) 3 }; )


$f.oge .ntgl

The $ f . o g emethod is triggered by the "click" event and .ntgl accepts two or more functions. Each time the click event occurs, the next function in the list is called. Generally, $ f . o g eis .ntgl used with just two functions; however, it will accept an unlimited number of functions. Be careful, though: providing a long list of functions can be difficult to debug).
The toggle helper function

1 $'.xadr)tgl( (pepne'.oge 2 fnto( { ucin) 3 $ti)pe(.dCas'pn) (hs.rv)adls(oe'; 4 } , 5 fnto( { ucin) 6 $ti)pe(.eoels(oe'; (hs.rv)rmvCas'pn) 7 } 8 ) ;

Exercises
Create an Input Hint
Open the file / x r i e / n e . t lin your browser. Use the eecssidxhm file / x r i e / s i p t i t j or work in Firebug. Your task eecssj/nuHn.s is to use the text of the label for the search input to create "hint" text for the search input. The steps are as follows: 1. Set the value of the search input to the text of the label element 2. Add a class of "hint" to the search input 3. Remove the label element
jqfundamentals.com/book/index.html#chapter-1 55/111

5/18/12

jQuery Fundamentals

4. Bind a focus event to the search input that removes the hint text and the "hint" class 5. Bind a blur event to the search input that restores the hint text and "hint" class if no search text was entered What other considerations might there be if you were creating this functionality for a real site?

Add Tabbed Navigation


Open the file / x r i e / n e . t lin your browser. Use the eecssidxhm file / x r i e / s t b . s Your task is to create tabbed eecssj/asj. navigation for the two div.module elements. To accomplish this: 1. Hide all of the modules. 2. Create an unordered list element before the first module. 3. Iterate over the modules using $ f . a h For each .nec. module, use the text of the h2 element as the text for a list item that you add to the unordered list element. 4. Bind a click event to the list item that: Shows the related module, and hides any other modules Adds a class of "current" to the clicked list item Removes the class "current" from the other list item 5. Finally, show the first tab.

Back to top

Effects
Overview
jQuery makes it trivial to add simple effects to your page. Effects can use the built-in settings, or provide a customized duration. You can also create custom animations of arbitrary CSS properties. For complete details on jQuery effects, visit http://api.jquery.com/category/effects/.

Built-in Effects
jqfundamentals.com/book/index.html#chapter-1 56/111

5/18/12

jQuery Fundamentals

Frequently used effects are built into jQuery as methods: $.fn.show Show the selected element. $.fn.hide Hide the selected elements. $.fn.fadeIn Animate the opacity of the selected elements to 100%. $.fn.fadeOut Animate the opacity of the selected elements to 0%. $.fn.slideDown Display the selected elements with a vertical sliding motion. $.fn.slideUp Hide the selected elements with a vertical sliding motion. $.fn.slideToggle Show or hide the selected elements with a vertical sliding motion, depending on whether the elements are currently visible.
Example 6.1: A basic use of a built-in effect

1 $'1)so(; (h'.hw)

Changing the Duration of Built-in Effects


With the exception of $ f . h wand $ f . i e all of the built-in .nso .nhd, methods are animated over the course of 400ms by default. Changing the duration of an effect is simple.
Example 6.2: Setting the duration of an effect

1 $'1)fdI(0) (h'.aen30; / fd i oe / ae n vr 30s 0m 2 $'1)fdOt'lw) / uigabit (h'.aeu(so'; / sn uli seddfnto n pe eiiin jQuery.fx.speeds jQuery has an object at j u r . x s e d that contains the Qeyf.pes default speed, as well as settings for " l w and " a t . so" fs" 1 sed:{ pes 2 so:60 lw 0,
jqfundamentals.com/book/index.html#chapter-1 57/111

5/18/12

jQuery Fundamentals

3 4 5 6 }

fs:20 sed aD al / tf0, pe / e ut _eal:40 dfut 0

It is possible to override or add to this object. For example, you may want to change the default duration of effects, or you may want to create your own effects speed.
Example 6.3: Augmenting jQuery.fx.speeds with custom speed definitions

1 jur.xsed.lzn =10 Qeyf.pesbaig 0; 2 jur.xsed.ute=20; Qeyf.pestrl 00

Doing Something when an Effect is Done


Often, you'll want to run some code once an animation is done if you run it before the animation is done, it may affect the quality of the animation, or it may remove elements that are part of the animation. [Definition: Callback functions provide a way to register your interest in an event that will happen in the future.] In this case, the event we'll be responding to is the conclusion of the animation. Inside of the callback function, the keyword t i refers to the element that the effect was called on; hs as we did inside of event handler functions, we can turn it into a jQuery object via $ t i ) (hs.
Example 6.4: Running code when an animation is complete

1 $'i.l'.aeu(0,fnto( { (dvod)fdOt30 ucin) $ti)rmv(;}; (hs.eoe) ) Note that if your selection doesn't return any elements, your callback will never run! You can solve this problem by testing whether your selection returned any elements; if not, you can just run the callback immediately.
Example 6.5: Run a callback even if there were no elements to animate

0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 1 0 1 1

vr$hn =$'nnxset) a tig (#oeitn'; vrc =fnto( { a b ucin) cnoelg'oe'; osl.o(dn!) } ; i (tiglnt){ f $hn.egh $hn.aen30 c) tigfdI(0, b; }es { le c(; b) }

Custom Effects with $ f . n m t .naiae


jQuery makes it possible to animate arbitrary CSS properties via the $ f . n m t method. The $ f . n m t method lets you .naiae .naiae
jqfundamentals.com/book/index.html#chapter-1 58/111

5/18/12

jQuery Fundamentals

animate to a set value, or to a value relative to the current value.


Example 6.6: Custom effects with $.fn.animate

1 $'i.utms)aiae (dvfnie'.nmt( 2 { 3 lf :"=0, et +5" 4 oaiy:02 pct .5 5 } , 6 30 / drto 0, / uain 7 fnto( {cnoelg'oe';/ ucin) osl.o(dn!) / clak abc 8 }; )

Note
Color-related properties cannot be animated with $ f . n m t using jQuery out of the box. Color animations .naiae can easily be accomplished by including the color plugin. We'll discuss using plugins later in the book.

Easing
[Definition: Easing describes the manner in which an effect occurs whether the rate of change is steady, or varies over the duration of the animation.] jQuery includes only two methods of easing: swing and linear. If you want more natural transitions in your animations, various easing plugins are available. As of jQuery 1.4, it is possible to do per-property easing when using the $.fn.animate method.
Example 6.7: Per-property easing

1 $'i.utms)aiae (dvfnie'.nmt( 2 { 3 lf :["=0,"wn"] et +5" sig , 4 oaiy:[02,"ier ] pct .5 lna" 5 } , 6 30 0 7 ) ; For more details on easing options, see http://api.jquery.com/animate/.

Managing Effects
jQuery provides several tools for managing animations. $.fn.stop Stop currently running animations on the selected
jqfundamentals.com/book/index.html#chapter-1 59/111

5/18/12

jQuery Fundamentals

elements. $.fn.delay Wait the specified number of milliseconds before running the next animation. 1 $'1)so(0)dly10)hd(0) (h'.hw30.ea(00.ie30; jQuery.fx.off If this value is true, there will be no transition for animations; elements will immediately be set to the target final state instead. This can be especially useful when dealing with older browsers; you also may want to provide the option to your users.

Exercises
Reveal Hidden Text
Open the file / x r i e / n e . t lin your browser. Use the eecssidxhm file / x r i e / s b o . s Your task is to add some eecssj/lgj. interactivity to the blog section of the page. The spec for the feature is as follows: Clicking on a headline in the #blog div should slide down the excerpt paragraph Clicking on another headline should slide down its excerpt paragraph, and slide up any other currently showing excerpt paragraphs. Hint: don't forget about the : i i l selector! vsbe

Create Dropdown Menus


Open the file / x r i e / n e . t lin your browser. Use the eecssidxhm file / x r i e / s n v g t o . s Your task is to add eecssj/aiainj. dropdowns to the main navigation at the top of the page. Hovering over an item in the main menu should show that item's submenu items, if any. Exiting an item should hide any submenu items. To accomplish this, use the $ f . o e method to add and .nhvr remove a class from the submenu items to control whether they're visible or hidden. (The file at / x r i e / s / t l s c sincludes the "hover" class for this eecsscssye.s purpose.)

Create a Slideshow
jqfundamentals.com/book/index.html#chapter-1 60/111

5/18/12

jQuery Fundamentals

Open the file / x r i e / n e . t lin your browser. Use the eecssidxhm file / x r i e / s s i e h w j . Your task is to take a plain eecssj/ldso.s semantic HTML page and enhance it with JavaScript by adding a slideshow. 1. Move the #slideshow element to the top of the body. 2. Write code to cycle through the list items inside the element; fade one in, display it for a few seconds, then fade it out and fade in the next one. 3. When you get to the end of the list, start again at the beginning. For an extra challenge, create a navigation area under the slideshow that shows how many images there are and which image you're currently viewing. (Hint: $.fn.prevAll will come in handy for this.)

Back to top

Ajax
Overview
The XMLHttpRequest method (XHR) allows browsers to communicate with the server without requiring a page reload. This method, also known as Ajax (Asynchronous JavaScript and XML), allows for web pages that provide rich, interactive experiences. Ajax requests are triggered by JavaScript code; your code sends a request to a URL, and when it receives a response, a callback function can be triggered to handle the response. Because the request is asynchronous, the rest of your code continues to execute while the request is being processed, so its imperative that a callback be used to handle the response. jQuery provides Ajax support that abstracts away painful browser differences. It offers both a full-featured $ a a ( .jx) method, and simple convenience methods such as $ g t ) .e(, $ g t c i t ) $ g t S N ) $ p s ( , and $ ) l a ( . .eSrp(, .eJO(, .ot) (.od) Most jQuery applications dont in fact use XML, despite the name Ajax; instead, they transport data as plain HTML or
jqfundamentals.com/book/index.html#chapter-1 61/111

5/18/12

jQuery Fundamentals

JSON (JavaScript Object Notation). In general, Ajax does not work across domains. Exceptions are services that provide JSONP (JSON with Padding) support, which allow limited cross-domain functionality.

Key Concepts
Proper use of Ajax-related jQuery methods requires understanding some key concepts first.

GET vs. Post


The two most common methods for sending a request to a server are GET and POST. Its important to understand the proper application of each. The GET method should be used for non-destructive operations that is, operations where you are only getting data from the server, not changing data on the server. For example, a query to a search service might be a GET request. GET requests may be cached by the browser, which can lead to unpredictable behavior if you are not expecting it. GET requests generally send all of their data in a query string. The POST method should be used for destructive operations that is, operations where you are changing data on the server. For example, a user saving a blog post should be a POST request. POST requests are generally not cached by the browser; a query string can be part of the URL, but the data tends to be sent separately as post data.

Data Types
jQuery generally requires some instruction as to the type of data you expect to get back from an Ajax request; in some cases the data type is specified by the method name, and in other cases it is provided as part of a configuration object. There are several options: text For transporting simple strings html For transporting blocks of HTML to be placed on the page script For adding a new script to the page json
jqfundamentals.com/book/index.html#chapter-1 62/111

5/18/12

jQuery Fundamentals

For transporting JSON-formatted data, which can include strings, arrays, and objects

Note
As of jQuery 1.4, if the JSON data sent by your server isn't properly formatted, the request may fail silently. See http://json.org for details on properly formatting JSON, but as a general rule, use built-in language methods for generating JSON on the server to avoid syntax issues. jsonp For transporting JSON data from another domain xml For transporting data in a custom XML schema I am a strong proponent of using the JSON format in most cases, as it provides the most flexibility. It is especially useful for sending both HTML and data at the same time.

A is for Asynchronous
The asynchronicity of Ajax catches many new jQuery users off guard. Because Ajax calls are asynchronous by default, the response is not immediately available. Responses can only be handled using a callback. So, for example, the following code will not work: 1 vrrsos; a epne 2 $gt'o.h' fnto(){rsos = .e(fopp, ucinr epne r }; ; ) 3 cnoelgrsos) / udfnd osl.o(epne; / neie! Instead, we need to pass a callback function to our request; this callback will run when the request succeeds, at which point we can access the data that it returned, if any. 1 $gt'o.h' fnto(epne { .e(fopp, ucinrsos) cnoelgrsos) }; osl.o(epne; )

Same-Origin Policy and JSONP


In general, Ajax requests are limited to the same protocol (http or https), the same port, and the same domain as the page making the request. This limitation does not apply to scripts that are loaded via jQuery's Ajax methods. The other exception is requests targeted at a JSONP service on another domain. In the case of JSONP, the provider of the
jqfundamentals.com/book/index.html#chapter-1 63/111

5/18/12

jQuery Fundamentals

service has agreed to respond to your request with a script that can be loaded into the page using a < c i t tag, thus avoiding srp> the same-origin limitation; that script will include the data you requested, wrapped in a callback function you provide.

Ajax and Firebug


Firebug (or the Webkit Inspector in Chrome or Safari) is an invaluable tool for working with Ajax requests. You can see Ajax requests as they happen in the Console tab of Firebug (and in the Resources > XHR panel of Webkit Inspector), and you can click on a request to expand it and see details such as the request headers, response headers, response content, and more. If something isn't going as expected with an Ajax request, this is the first place to look to track down what's wrong.

jQuery's Ajax-Related Methods


While jQuery does offer many Ajax-related convenience methods, the core $ a a method is at the heart of all of them, .jx and understanding it is imperative. We'll review it first, and then touch briefly on the convenience methods. I generally use the $.ajax method and do not use convenience methods. As you'll see, it offers features that the convenience methods do not, and its syntax is more easily understandable, in my opinion.

$.ajax
jQuerys core $ a a method is a powerful and straightforward .jx way of creating Ajax requests. It takes a configuration object that contains all the instructions jQuery requires to complete the request. The $ a a method is particularly valuable because it .jx offers the ability to specify both success and failure callbacks. Also, its ability to take a configuration object that can be defined separately makes it easier to write reusable code. For complete documentation of the configuration options, visit http://api.jquery.com/jQuery.ajax/.
Example 7.1: Using the core $.ajax method

0 $aa( 1 .jx{ 0 2 / teULfrterqet / h R o h eus 0 3 ul:'otpp, r ps.h' 0 4 0 5 / tedt t sn / h aa o ed 0 6 / (ilb cnetdt aqey / wl e ovre o ur srn) tig 0 7 dt :{i :13} aa d 2 , 0 8 0 9 / wehrti i aPS o GT / hte hs s OT r E rqet eus
jqfundamentals.com/book/index.html#chapter-1 64/111

5/18/12

jQuery Fundamentals

1 1 0 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7

tp :'E' ye GT, / tetp o dt w epc bc / h ye f aa e xet ak dtTp :'sn, aaye jo' / cd t rni terqetsced; / oe o u f h eus uces / tersos i pse t te / h epne s asd o h fnto ucin sces:fnto(sn { ucs ucinjo) $'h/'.etjo.il)apnT(bd'; (<1>)tx(sntte.pedo'oy) $'dvcas"otn">) (<i ls=cnet/' .tljo.tl.pedo'oy) hm(snhm)apnT(bd'; } ,

/ cd t rni terqetfis / oe o u f h eus al; / terwrqetadsau cdsae / h a eus n tts oe r / pse t tefnto / asd o h ucin err:fnto(h,sau){ ro ucinxr tts aet'or,teewsa lr(Sry hr a polm'; rbe!) 2 8 } , 2 9 3 0 / cd t rnrgrls o sceso / oe o u eades f ucs r fiue alr 3 1 cmlt :fnto(h,sau){ opee ucinxr tts 3 2 aet'h rqeti cmlt!) lr(Te eus s opee'; 3 3 } 3 }; 4 )

Note
A note about the d t T p setting: if the server sends back aaye data that is in a different format than you specify, your code may fail, and the reason will not always be clear, because the HTTP response code will not show an error. When working with Ajax requests, make sure your server is sending back the data type you're asking for, and verify that the Contenttype header is accurate for the data type. For example, for JSON data, the Content-type header should be apiainjo. plcto/sn

$ a a Options .jx

There are many, many options for the $.ajax method, which is part of its power. For a complete list of options, visit http://api.jquery.com/jQuery.ajax/; here are several that you will use frequently: async Set to f l eif the request should be sent synchronously. as Defaults to t u . Note that if you set this option to false, re your request will block execution of other code until the response is received.
jqfundamentals.com/book/index.html#chapter-1 65/111

5/18/12

jQuery Fundamentals

cache Whether to use a cached response if available. Defaults to t u for all dataTypes except "script" and "jsonp". When re set to false, the URL will simply have a cachebusting parameter appended to it. complete A callback function to run when the request is complete, regardless of success or failure. The function receives the raw request object and the text status of the request. context The scope in which the callback function(s) should run (i.e. what t i will mean inside the callback function(s)). By hs default, t i inside the callback function(s) refers to the hs object originally passed to $ a a . .jx data The data to be sent to the server. This can either be an object or a query string, such as f o b r b z b m o=a&a=i. dataType The type of data you expect back from the server. By default, jQuery will look at the MIME type of the response if no dataType is specified. error A callback function to run if the request results in an error. The function receives the raw request object and the text status of the request. jsonp The callback name to send in a query string when making a JSONP request. Defaults to "callback". success A callback function to run if the request succeeds. The function receives the response data (converted to a JavaScript object if the dataType was JSON), as well as the text status of the request and the raw request object. timeout The time in milliseconds to wait before considering the request a failure. traditional
jqfundamentals.com/book/index.html#chapter-1 66/111

5/18/12

jQuery Fundamentals

Set to true to use the param serialization style in use prior to jQuery 1.4. For details, see http://api.jquery.com/jQuery.param/. type The type of the request, "POST" or "GET". Defaults to "GET". Other request types, such as "PUT" and "DELETE" can be used, but they may not be supported by all browsers. url The URL for the request. The u loption is the only required property of the $ a a r .jx configuration object; all other properties are optional.

Convenience Methods
If you don't need the extensive configurability of $ a a , and you .jx don't care about handling errors, the Ajax convenience functions provided by jQuery can be useful, terse ways to accomplish Ajax requests. These methods are just "wrappers" around the core $ a a method, and simply pre-set some of the options on the .jx $ a a method. .jx The convenience methods provided by jQuery are: $.get Perform a GET request to the provided URL. $.post Perform a POST request to the provided URL. $.getScript Add a script to the page. $.getJSON Perform a GET request, and expect JSON to be returned. In each case, the methods take the following arguments, in order: url The URL for the request. Required. data The data to be sent to the server. Optional. This can either be an object or a query string, such as f o b r b z b m o=a&a=i.
jqfundamentals.com/book/index.html#chapter-1 67/111

5/18/12

jQuery Fundamentals

Note
This option is not valid for $ g t c i t .eSrp. success callback A callback function to run if the request succeeds. Optional. The function receives the response data (converted to a JavaScript object if the data type was JSON), as well as the text status of the request and the raw request object. data type The type of data you expect back from the server. Optional.

Note
This option is only applicable for methods that don't already specify the data type in their name.

Example 7.2: Using jQuery's Ajax convenience methods

0 / gtpantx o hm 1 / e li et r tl 0 $gt'uespp,{ueI :13 } 2 .e(/sr.h' srd 24 , fnto(ep { ucinrs) 0 3 cnoelgrs) osl.o(ep; 0 }; 4 ) 0 5 0 / adasrp t tepg,te rna 6 / d cit o h ae hn u fnto dfndi i ucin eie n t 0 $gtcit'sai/smSrp.s, 7 .eSrp(/ttcj/ycitj' fnto( { ucin) 0 8 fntoFoMSrp(; ucinrmycit) 0 }; 9 ) 1 0 1 / gtJO-omte dt fo tesre 1 / e SNfratd aa rm h evr 1 $gtSN'dtispp,fnto(ep { 2 .eJO(/eal.h' ucinrs) 1 3 $ec(ep fnto(,v { .ahrs, ucink ) 1 4 cnoelgk+':'+v; osl.o( ) 1 5 }; ) 1 }; 6 )
$f.od .nla

The $ f . o dmethod is unique among jQuerys Ajax methods .nla in that it is called on a selection. The $ f . o dmethod fetches .nla HTML from a URL, and uses the returned HTML to populate the selected element(s). In addition to providing a URL to the method, you can optionally provide a selector; jQuery will fetch only the matching content from the returned HTML.
jqfundamentals.com/book/index.html#chapter-1 68/111

5/18/12

jQuery Fundamentals

Example 7.3: Using $.fn.load to populate an element

1 $'nwotn'.od'fohm'; (#eCnet)la(/o.tl)
Example 7.4: Using $.fn.load to populate an element based on a selector

1 $'nwotn'.od'fohm #yi (#eCnet)la(/o.tl mDv h:is' fnto(tl { 1frt, ucinhm) 2 aet'otn udtd'; lr(Cnet pae!) 3 }; )

Ajax and Forms


jQuerys ajax capabilities can be especially useful when dealing with forms. The jQuery Form Plugin is a well-tested tool for adding Ajax capabilities to forms, and you should generally use it for handling forms with Ajax rather than trying to roll your own solution for anything remotely complex. That said, there are a two jQuery methods you should know that relate to form processing in jQuery: $ f . e i l z and $ f . e i l z A r y .nsraie .nsraiera.
Example 7.5: Turning form data into a query string

1 $'mFr'.eilz(; (#yom)sraie)
Example 7.6: Creating an array of objects containing form data

1 $'mFr'.eilzAry) (#yom)sraiera(; 2 3 / cetsasrcuelk ti: / rae tutr ie hs 4 [ 5 {nm :'il1,vle:13} ae fed' au 2 , 6 {nm :'il2,vle:'el ae fed' au hlo wrd } ol' 7 ]

Working with JSONP


The advent of JSONP essentially a consensual cross-site scripting hack has opened the door to powerful mashups of content. Many prominent sites provide JSONP services, allowing you access to their content via a predefined API. A particularly great source of JSONP-formatted data is the Yahoo! Query Language, which we'll use in the following example to fetch news about cats.
Example 7.7: Using YQL and JSONP

0 $aa( 1 .jx{ 0 2 ul: r 'tp/qeyyhopscmv/ulcyl, ht:/ur.aoai.o/1pbi/q' 0 3 0 4 / tenm o teclbc prmtr / h ae f h alak aaee, 0 5 / a seiidb teYLsrie / s pcfe y h Q evc 0 6 jop:'alak, sn clbc'
jqfundamentals.com/book/index.html#chapter-1 69/111

5/18/12

jQuery Fundamentals

0 7 8 0 9 1 0 1 1 1 2 1 3

/ tl jur w'eepcigJOP / el Qey er xetn SN dtTp :'sn' aaye jop, / tl YLwa w wn adta w / el Q ht e at n ht e wn JO at SN dt :{ aa q:'eettteasrc,r fo slc il,btatul rm sac.esweeqey"a", erhnw hr ur=ct' fra :'sn omt jo' } ,

1 4 1 5 1 6 1 7 / wr wt tersos / ok ih h epne 1 8 sces:fnto(epne { ucs ucinrsos) 1 9 cnoelgrsos) osl.o(epne; 2 0 } 2 }; 1 )

jQuery handles all the complex aspects of JSONP behind-thescenes all we have to do is tell jQuery the name of the JSONP callback parameter specified by YQL ("callback" in this case), and otherwise the whole process looks and feels like a normal Ajax request.

Ajax Events
Often, youll want to perform an operation whenever an Ajax requests starts or stops, such as showing or hiding a loading indicator. Rather than defining this behavior inside every Ajax request, you can bind Ajax events to elements just like you'd bind other events. For a complete list of Ajax events, visit http://docs.jquery.com/Ajax_Events.
Example 7.8: Setting up a loading indicator using Ajax Events

1 $'laigidctr) (#odn_niao' 2 .jxtr(ucin){$ti)so(; aaSatfnto( (hs.hw) } ) 3 .jxtpfnto( {$ti)hd(; aaSo(ucin) (hs.ie) }; )

Exercises
Load External Content
Open the file / x r i e / n e . t lin your browser. Use the eecssidxhm file / x r i e / s l a . s Your task is to load the content of a eecssj/odj. blog item when a user clicks on the title of the item. 1. Create a target div after the headline for each blog post and store a reference to it on the headline element using $f.aa .ndt. 2. Bind a click event to the headline that will use the $ f . o dmethod to load the appropriate content from .nla / x r i e / a a b o . t linto the target div. Don't eecssdt/lghm forget to prevent the default action of the click event.
jqfundamentals.com/book/index.html#chapter-1 70/111

5/18/12

jQuery Fundamentals

Note that each blog headline in index.html includes a link to the post. You'll need to leverage the href of that link to get the proper content from blog.html. Once you have the href, here's one way to process it into an ID that you can use as a selector in $f.od .nla: 1 vrhe ='lghm#ot' a rf bo.tlps1; 2 vrtmAry=he.pi(#) a epra rfslt''; 3 vri =''+tmAry1; a d # epra[] Remember to make liberal use of c n o e l gto make sure osl.o you're on the right path!

Load Content Using JSON


Open the file / x r i e / n e . t lin your browser. Use the eecssidxhm file / x r i e / s s e i l . s Your task is to show the user eecssj/pcasj. details about the special for a given day when the user selects a day from the select dropdown. 1. Append a target div after the form that's inside the #specials element; this will be where you put information about the special once you receive it. 2. Bind to the change event of the select element; when the user changes the selection, send an Ajax request to /xrie/aaseil.sn eecssdt/pcasjo. 3. When the request returns a response, use the value the user selected in the select (hint: $ f . a ) to look up .nvl information about the special in the JSON response. 4. Add some HTML about the special to the target div you created. 5. Finally, because the form is now Ajax-enabled, remove the submit button from the form. Note that we're loading the JSON every time the user changes their selection. How could we change the code so we only make the request once, and then use a cached response when the user changes their choice in the select?

Back to top

Plugins
What exactly is a plugin?
jqfundamentals.com/book/index.html#chapter-1 71/111

5/18/12

jQuery Fundamentals

A jQuery plugin is simply a new method that we use to extend jQuery's prototype object. By extending the prototype object you enable all jQuery objects to inherit any methods that you add. As established, whenever you call j u r ( you're creating Qey) a new jQuery object, with all of jQuery's methods inherited. The idea of a plugin is to do something with a collection of elements. You could consider each method that comes with the jQuery core a plugin, like f d O tor a d l s . aeu dCas You can make your own plugins and use them privately in your code or you can release them into the wild. There are thousands of jQuery plugins available online. The barrier to creating a plugin of your own is so low that you'll want to do it straight away!

How to create a basic plugin


The notation for creating a typical plugin is as follows: 1 (ucin${ fnto() 2 $f.yePui =fnto( { .nmNwlgn ucin) 3 rtr ti.ahfnto({ eun hsec(ucin) 4 / d smtig / o oehn 5 }; ) 6 } ; 7 }jur); (Qey) Don't let that confuse you though. The point of a jQuery plugin is to extend jQuery's prototype object, and that's what's happening on this line: 1 $f.yePui =fnto( {/.. .nmNwlgn ucin) /. We wrap this assignment in an immediately-invoked function: 1 (ucin${ fnto() 2 /.. /. 3 }jur); (Qey) This has the effect of creating a "private" scope that allows us to extend jQuery using the dollar symbol without having to risk the possibility that the dollar has been overwritten by another library. So our actual plugin, thus far, is this: 1 $f.yePui =fnto( { .nmNwlgn ucin) 2 rtr ti.ahfnto({ eun hsec(ucin) 3 / d smtig / o oehn 4 }; ) 5 } ; The t i keyword within the new plugin refers to the jQuery hs object on which the plugin is being called.
jqfundamentals.com/book/index.html#chapter-1 72/111

5/18/12

jQuery Fundamentals

1 2 3 4 5 6 7

vrsmjurOjc =$'smtig) a oeQeybet (#oehn'; $f.yePui =fnto( { .nmNwlgn ucin) aetti ==smjurOjc) lr(hs = oeQeybet; } ; smjurOjc.yePui(;/ aet oeQeybetmNwlgn) / lrs 're tu'

Your typical jQuery object will contain references to any number of DOM elements, and that's why jQuery objects are often referred to as collections. So, to do something with a collection we need to loop through it, which is most easily achieved using jQuery's e c ( method: ah) 1 $f.yePui =fnto( { .nmNwlgn ucin) 2 rtr ti.ahfnto({ eun hsec(ucin) 3 4 }; ) 5 } ; jQuery's e c ( method, like most other jQuery methods, ah) returns a jQuery object, thus enabling what we've all come to know and love as 'chaining' ($ . . . s ( . t r ) . ). We (.)cs)at(.. wouldn't want to break this convention so we return the t i hs object. Within this loop you can do whatever you want with each element. Here's an example of a small plugin using some of the techniques we've discussed: 0 (ucin${ 1 fnto() 0 2 $f.hwikoain=fnto( { .nsoLnLcto ucin) 0 3 rtr eun ti.itr''.ahfnto({ hsfle(a)ec(ucin) 0 4 $ti)apn( (hs.ped 0 5 '( +$ti)at(he' ' (hs.tr'rf) +'' ) 0 6 ) ; 0 7 }; ) 0 8 } ; 0 }jur); 9 (Qey) 1 0 1 / Uaeeape 1 / sg xml: 1 $''.hwikoain) 2 (a)soLnLcto(; This handy plugin goes through all anchors in the collection and appends the h e attribute in brackets. rf 1 2 3 4 5 <- Bfr pui i cle:-> !- eoe lgn s ald < he=pg.tl>o<a a rf"aehm"Fo/> <- Atrpui i cle:-> !- fe lgn s ald < he=pg.tl>o (aehm)/> a rf"aehm"Fo pg.tl<a

Our plugin can be optimised though: 1 (ucin${ fnto() 2 $f.hwikoain=fnto( { .nsoLnLcto ucin) 3 rtr eun ti.itr''.pedfnto({ hsfle(a)apn(ucin)
jqfundamentals.com/book/index.html#chapter-1 73/111

5/18/12

jQuery Fundamentals

5 }; ) 6 } ; 7 }jur); (Qey) We're using the a p n method's capability to accept a callback, ped and the return value of that callback will determine what is appended to each element in the collection. Notice also that we're not using the a t method to retrieve the h e attribute, tr rf because the native DOM API gives us easy access with the aptly named h e property. rf Here's another example of a plugin. This one doesn't require us to loop through every elememt with the e c ( method. Instead, ah) we're simply going to delegate to other jQuery methods directly: 0 (ucin${ 1 fnto() 0 2 $f.aennAdls = .nfdIAddCas fnto(uain casae { ucindrto, lsNm) 0 3 rtr ti.aendrto, eun hsfdI(uain fnto({ ucin) 0 4 $ti)adls(lsNm) (hs.dCascasae; 0 5 }; ) 0 6 } ; 0 }jur); 7 (Qey) 0 8 0 / Uaeeape 9 / sg xml: 1 $''.aennAdls(0, 0 (a)fdIAddCas40 'iihdaig) fnseFdn';

'' );

rtr '( +ti.rf+ eun ' hshe

Finding & Evaluating Plugins


Plugins extend the basic jQuery functionality, and one of the most celebrated aspects of the library is its extensive plugin ecosystem. From table sorting to form validation to autocompletion ... if theres a need for it, chances are good that someone has written a plugin for it. The quality of jQuery plugins varies widely. Many plugins are extensively tested and well-maintained, but others are hastily created and then ignored. More than a few fail to follow best practices. Google is your best initial resource for locating plugins, though the jQuery team is working on an improved plugin repository. Once youve identified some options via a Google search, you may want to consult the jQuery mailing list or the #jquery IRC channel to get input from others. When looking for a plugin to fill a need, do your homework. Ensure that the plugin is well-documented, and look for the author to provide lots of examples of its use. Be wary of plugins that do far more than you need; they can end up adding substantial overhead to your page. For more tips on spotting a
jqfundamentals.com/book/index.html#chapter-1 74/111

5/18/12

jQuery Fundamentals

subpar plugin, read Signs of a poorly written jQuery plugin by Remy Sharp. Once you choose a plugin, youll need to add it to your page. Download the plugin, unzip it if necessary, place it your applications directory structure, then include the plugin in your page using a script tag (after you include jQuery).

Writing Plugins
Sometimes you want to make a piece of functionality available throughout your code; for example, perhaps you want a single method you can call on a jQuery selection that performs a series of operations on the selection. In this case, you may want to write a plugin. Most plugins are simply methods created in the $ f namespace. .n jQuery guarantees that a method called on a jQuery object will be able to access that jQuery object as t i inside the method. hs In return, your plugin needs to guarantee that it returns the same object it received, unless explicitly documented otherwise. Here is an example of a simple plugin:
Example 8.1: Creating a plugin to add and remove a class on hover

0 / dfnn tepui 1 / eiig h lgn 0 (ucin${ 2 fnto() 0 3 $f.oeCas=fnto(){ .nhvrls ucinc 0 4 rtr ti.oe( eun hshvr 0 5 fnto( { ucin) $ti)tglCasc;} (hs.ogels() 0 6 ) ; 0 7 } ; 0 }(Qey; 8 )jur) 0 9 1 / uigtepui 0 / sn h lgn 1 $'i)hvrls(hvr) 1 (l'.oeCas'oe'; For more on plugin development, read Mike Alsup's essential post, A Plugin Development Pattern. In it, he creates a plugin called $ f . i i h , which provides support for the metadata .nhlgt plugin if it's present, and provides a centralized method for setting global and instance options for the plugin.
Example 8.2: The Mike Alsup jQuery Plugin Development Pattern

0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9

/ / / cet coue / rae lsr / / (ucin$ { fnto() / / / pui dfnto / lgn eiiin / / $f.iih =fnto(pin){ .nhlgt ucinotos dbgti) eu(hs;
75/111

jqfundamentals.com/book/index.html#chapter-1

5/18/12

jQuery Fundamentals

1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 3 9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1

/ bidmi otosbfr eeet / ul an pin eoe lmn ieain trto vrot =$etn(} a ps .xed{, $f.iih.eals otos; .nhlgtdfut, pin) / ieaeadrfra ec mthd / trt n eomt ah ace eeet lmn rtr ti.ahfnto( { eun hsec(ucin) $hs=$ti) ti (hs; / bideeetseii otos / ul lmn pcfc pin vro=$mt ?$etn(} ot, a .ea .xed{, ps $hsdt():ot; ti.aa) ps / udt eeetsye / pae lmn tls $hscs{ ti.s( bcgonClr obcgon, akrudoo: .akrud clr ofrgon oo: .oerud }; ) vrmru =$hshm(; a akp ti.tl) / cl orfra fnto / al u omt ucin mru =$f.iih.omtmru) akp .nhlgtfra(akp; $hshm(akp; ti.tlmru) }; ) } ; / / / piaefnto frdbgig / rvt ucin o eugn / / fnto dbg$b){ ucin eu(oj i (idwcnoe& f wno.osl & wno.osl.o) idwcnoelg wno.osl.o(hlgtslcin idwcnoelg'iih eeto cut '+$b.ie); on: ojsz() } ; / / / dfn adeps orfra fnto / eie n xoe u omt ucin / / $f.iih.omt=fnto(x){ .nhlgtfra ucintt rtr 'srn> +tt+'/tog' eun <tog' x <srn>; } ; / / / pui dfut / lgn eals / / $f.iih.eals={ .nhlgtdfut frgon:'e' oerud rd, bcgon:'elw akrud ylo' } ; / / / edo coue / n f lsr / / }(Qey; )jur)

Writing Stateful Plugins with the jQuery UI Widget Factory


Note
This section is based, with permission, on the blog post Building Stateful jQuery Plugins by Scott Gonzalez.

While most existing jQuery plugins are stateless that is, we


jqfundamentals.com/book/index.html#chapter-1 76/111

5/18/12

jQuery Fundamentals

call them on an element and that is the extent of our interaction with the plugin theres a large set of functionality that doesnt fit into the basic plugin pattern. In order to fill this gap, jQuery UI has implemented a more advanced plugin system. The new system manages state, allows multiple functions to be exposed via a single plugin, and provides various extension points. This system is called the widget factory and is exposed as j u r . i g tas part of jQuery UI 1.8; Qeywde however, it can be used independently of jQuery UI. To demonstrate the capabilities of the widget factory, we'll build a simple progress bar plugin. To start, well create a progress bar that just lets us set the progress once. As we can see below, this is done by calling j u r . i g twith two parameters: the name of the plugin to Qeywde create and an object literal containing functions to support our plugin. When our plugin gets called, it will create a new plugin instance and all functions will be executed within the context of that instance. This is different from a standard jQuery plugin in two important ways. First, the context is an object, not a DOM element. Second, the context is always a single object, never a collection.
Example 8.3: A simple, stateful plugin using the jQuery UI widget factory

1 $wde(nkporsbr,{ .igt"m.rgesa" 2 _rae fnto( { cet: ucin) 3 vrpors =ti.pin.au + a rges hsotosvle "" %; 4 ti.lmn hseeet 5 .dCas"rgesa" adls(porsbr) 6 .etpors) tx(rges; 7 } 8 }; ) The name of the plugin must contain a namespace; in this case weve used the n knamespace. There is a limitation that m namespaces be exactly one level deep that is, we can't use a namespace like n k f o We can also see that the widget factory m.o. has provided two properties for us. t i . l m n is a jQuery hseeet object containing exactly one element. If our plugin is called on a jQuery object containing multiple elements, a separate plugin instance will be created for each element, and each instance will have its own t i . l m n . The second property, t i . p i n , hseeet hsotos is a hash containing key/value pairs for all of our plugins options. These options can be passed to our plugin as shown here.

Note
jqfundamentals.com/book/index.html#chapter-1 77/111

5/18/12

jQuery Fundamentals

In our example we use the n knamespace. The u m i namespace is reserved for official jQuery UI plugins. When building your own plugins, you should create your own namespace. This makes it clear where the plugin came from and whether it is part of a larger collection.

Example 8.4: Passing options to a widget

1 $"dv<dv" (<i>/i>) 2 .pedo "oy ) apnT( bd" 3 .rgesa( vle 2 }; porsbr{ au: 0 ) When we call j u r . i g tit extends jQuery by adding a Qeywde method to j u r . n(the same way we'd create a standard Qeyf plugin). The name of the function it adds is based on the name you pass to j u r . i g t without the namespace; in our case it Qeywde, will create j u r . n p o r s b r The options passed to our Qeyf.rgesa. plugin get set in t i . p i n inside of our plugin instance. As hsotos shown below, we can specify default values for any of our options. When designing your API, you should figure out the most common use case for your plugin so that you can set appropriate default values and make all options truly optional.
Example 8.5: Setting default options for a widget

0 $wde(nkporsbr,{ 1 .igt"m.rgesa" 0 2 / dfutotos / eal pin 0 3 otos { pin: 0 4 vle 0 au: 0 5 } , 0 6 0 7 _rae fnto( { cet: ucin) 0 8 vrpors =ti.pin.au + a rges hsotosvle "" %; 0 9 ti.lmn hseeet 1 0 .dCas "rgesa") adls( porsbr 1 1 .et pors ) tx( rges ; 1 2 } 1 }; 3 )

Adding Methods to a Widget


Now that we can initialize our progress bar, well add the ability to perform actions by calling methods on our plugin instance. To define a plugin method, we just include the function in the object literal that we pass to j u r . i g t We can also define Qeywde. private methods by prepending an underscore to the function name.
Example 8.6: Creating widget methods

0 $wde(nkporsbr,{ 1 .igt"m.rgesa" 0 2 otos { pin: 0 3 vle 0 au:


jqfundamentals.com/book/index.html#chapter-1 78/111

5/18/12

jQuery Fundamentals

0 4 0 5 0 6 0 7 0 8 0 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9

} , _rae fnto( { cet: ucin) vrpors =ti.pin.au + a rges hsotosvle "" %; ti.lmn hseeet .dCas"rgesa" adls(porsbr) .etpors) tx(rges; } , / cet apbi mto / rae ulc ehd vle fnto(au){ au: ucinvle / n vlepse,ata agte / o au asd c s etr i (au ==udfnd { f vle = neie) rtr ti.pin.au; eun hsotosvle / vlepse,ata aste / au asd c s etr }es { le ti.pin.au = hsotosvle ti.cntanvle; hs_osri(au) vrpors = a rges ti.pin.au +"" hsotosvle %; ti.lmn.etpors) hseeettx(rges; } } , / cet apiaemto / rae rvt ehd _osri:fnto(au){ cntan ucinvle i (au >10 { f vle 0) vle=10 au 0; } i (au <0 { f vle ) vle=0 au ; } rtr vle eun au;

3 0 3 1 3 2 3 3 3 4 3 5 } 3 }; 6 )

To call a method on a plugin instance, you pass the name of the method to the jQuery plugin. If you are calling a method that accepts parameters, you simply pass those parameters after the method name.
Example 8.7: Calling methods on a plugin instance

0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 1 0 1 1 1 2

vrbr=$"dv<dv" a a (<i>/i>) .pedo"oy) apnT(bd" .rgesa( vle 2 }; porsbr{ au: 0 ) / gttecretvle / e h urn au aetbrporsbr"au") lr(a.rgesa(vle); / udt tevle / pae h au brporsbr"au" 5) a.rgesa(vle, 0; / gttecretvleaan / e h urn au gi aetbrporsbr"au") lr(a.rgesa(vle);

Note
Executing methods by passing the method name to the
jqfundamentals.com/book/index.html#chapter-1 79/111

5/18/12

jQuery Fundamentals

same jQuery function that was used to initialize the plugin may seem odd. This is done to prevent pollution of the jQuery namespace while maintaining the ability to chain method calls.

Working with Widget Options


One of the methods that is automatically available to our plugin is the o t o method. The option method allows you to get and pin set options after initialization. This method works exactly like jQuerys css and attr methods: you can pass just a name to use it as a setter, a name and value to use it as a single setter, or a hash of name/value pairs to set multiple values. When used as a getter, the plugin will return the current value of the option that corresponds to the name that was passed in. When used as a setter, the plugins _ e O t o method will be called for each stpin option that is being set. We can specify a _ e O t o method in stpin our plugin to react to option changes.
Example 8.8: Responding when an option is set

0 $wde(nkporsbr,{ 1 .igt"m.rgesa" 0 2 otos { pin: 0 3 vle 0 au: 0 4 } , 0 5 0 6 _rae fnto( { cet: ucin) 0 7 ti.lmn.dCas"rgesa"; hseeetadls(porsbr) 0 8 ti.udt(; hs_pae) 0 9 } , 1 0 1 1 _eOto:fnto(e,vle { stpin ucinky au) 1 2 ti.pin[e]=vle hsotosky au; 1 3 ti.udt(; hs_pae) 1 4 } , 1 5 1 6 _pae fnto( { udt: ucin) 1 7 vrpors =ti.pin.au + a rges hsotosvle "" %; 1 8 ti.lmn.etpors) hseeettx(rges; 1 9 } 2 }; 0 )

Adding Callbacks
One of the easiest ways to make your plugin extensible is to add callbacks so users can react when the state of your plugin changes. We can see below how to add a callback to our progress bar to signify when the progress has reached 100%. The _ r g e method takes three parameters: the name of the tigr callback, a native event object that initiated the callback, and a hash of data relevant to the event. The callback name is the only required parameter, but the others can be very useful for users who want to implement custom functionality on top of your
jqfundamentals.com/book/index.html#chapter-1 80/111

5/18/12

jQuery Fundamentals

plugin. For example, if we were building a draggable plugin, we could pass the native mousemove event when triggering a drag callback; this would allow users to react to the drag based on the x/y coordinates provided by the event object.
Example 8.9: Providing callbacks for user extension

0 $wde(nkporsbr,{ 1 .igt"m.rgesa" 0 2 otos { pin: 0 3 vle 0 au: 0 4 } , 0 5 0 6 _rae fnto( { cet: ucin) 0 7 ti.lmn.dCas"rgesa"; hseeetadls(porsbr) 0 8 ti.udt(; hs_pae) 0 9 } , 1 0 1 1 _eOto:fnto(e,vle { stpin ucinky au) 1 2 ti.pin[e]=vle hsotosky au; 1 3 ti.udt(; hs_pae) 1 4 } , 1 5 1 6 _pae fnto( { udt: ucin) 1 7 vrpors =ti.pin.au + a rges hsotosvle "" %; 1 8 ti.lmn.etpors) hseeettx(rges; 1 9 i (hsotosvle= 10 { f ti.pin.au = 0) 2 0 ti.tigr"opee,nl, hs_rge(cmlt" ul {vle 10}; au: 0 ) 2 1 } 2 2 } 2 }; 3 ) Callback functions are essentially just additional options, so you can get and set them just like any other option. Whenever a callback is executed, a corresponding event is triggered as well. The event type is determined by concatenating the plugin name and the callback name. The callback and event both receive the same two parameters: an event object and a hash of data relevant to the event, as well see below. If your plugin has functionality that you want to allow the user to prevent, the best way to support this is by creating cancelable callbacks. Users can cancel a callback, or its associated event, the same way they cancel any native event: by calling e e t p e e t e a l ( or using r t r f l e If the user vn.rvnDfut) eun as. cancels the callback, the _ r g e method will return false so tigr you can implement the appropriate functionality within your plugin.
Example 8.10: Binding to widget events

0 vrbr=$"dv<dv" 1 a a (<i>/i>) 0 2 .pedo"oy) apnT(bd" 0 3 .rgesa( porsbr{ 0 4 0 5


jqfundamentals.com/book/index.html#chapter-1

cmlt:fnto(vn,dt){ opee ucineet aa aet "alak aeget" lr( Clbcs r ra!


81/111

5/18/12

jQuery Fundamentals

0 6 0 7 0 8

} } ) .id"rgesacmlt" bn(porsbropee, fnto(vn,dt){ ucineet aa 0 9 aet"vnsbbl adspot lr(Eet ube n upr mn hnlr freteefeiiiy"; ay ades o xrm lxblt.) 1 0 aet"h pors brvlei " lr(Te rges a au s +dt.au) aavle; 1 1 }; ) 1 2 1 brporsbr"pin,"au" 10; 3 a.rgesa(oto" vle, 0) The Widget Factory: Under the Hood When you call j u r . i g t it creates a constructor function Qeywde, for your plugin and sets the object literal that you pass in as the prototype for your plugin instances. All of the functionality that automatically gets added to your plugin comes from a base widget prototype, which is defined as j u r . i g t p o o y e QeyWde.rttp. When a plugin instance is created, it is stored on the original DOM element using j u r . a a with the plugin name as the Qeydt, key. Because the plugin instance is directly linked to the DOM element, you can access the plugin instance directly instead of going through the exposed plugin method if you want. This will allow you to call methods directly on the plugin instance instead of passing method names as strings and will also give you direct access to the plugins properties. 0 vrbr=$"dv<dv" 1 a a (<i>/i>) 0 2 .pedo"oy) apnT(bd" 0 3 .rgesa( porsbr) 0 4 .aa"rgesa") dt(porsbr ; 0 5 0 / cl amto drcl o tepui 6 / al ehd iety n h lgn isac ntne 0 broto(vle,5) 7 a.pin"au" 0; 0 8 0 / acs poete o tepui isac 9 / ces rpris n h lgn ntne 1 aetbrotosvle; 0 lr(a.pin.au) One of the biggest benefits of having a constructor and prototype for a plugin is the ease of extending the plugin. By adding or modifying methods on the plugins prototype, we can modify the behavior of all instances of our plugin. For example, if we wanted to add a method to our progress bar to reset the progress to 0% we could add this method to the prototype and it would instantly be available to be called on any plugin instance. 1 $nkporsbrpooyerst= .m.rgesa.rttp.ee fnto( { ucin) 2 ti.stpin"au" 0; hs_eOto(vle, ) 3 } ;

) ;

Cleaning Up
jqfundamentals.com/book/index.html#chapter-1 82/111

5/18/12

jQuery Fundamentals

In some cases, it will make sense to allow users to apply and then later unapply your plugin. You can accomplish this via the destroy method. Within the d s r ymethod, you should undo eto anything your plugin may have done during initialization or later use. The d s r ymethod is automatically called if the element eto that your plugin instance is tied to is removed from the DOM, so this can be used for garbage collection as well. The default d s r ymethod removes the link between the DOM element eto and the plugin instance, so its important to call the base function from your plugins d s r ymethod. eto
Example 8.11: Adding a destroy method to a widget

0 $wde("m.rgesa" { 1 .igt nkporsbr, 0 2 otos { pin: 0 3 vle 0 au: 0 4 } , 0 5 0 6 _rae fnto( { cet: ucin) 0 7 ti.lmn.dCas"rgesa"; hseeetadls(porsbr) 0 8 ti.udt(; hs_pae) 0 9 } , 1 0 1 1 _eOto:fnto(e,vle { stpin ucinky au) 1 2 ti.pin[e]=vle hsotosky au; 1 3 ti.udt(; hs_pae) 1 4 } , 1 5 1 6 _pae fnto( { udt: ucin) 1 7 vrpors =ti.pin.au + a rges hsotosvle "" %; 1 8 ti.lmn.etpors) hseeettx(rges; 1 9 i (hsotosvle= 10){ f ti.pin.au = 0 2 0 ti.tigr"opee,nl, hs_rge(cmlt" ul {vle 10}; au: 0 ) 2 1 } 2 2 } , 2 3 2 4 dsry fnto( { eto: ucin) 2 5 ti.lmn hseeet 2 6 .eoels(porsbr) rmvCas"rgesa" 2 7 .et") tx("; 2 8 2 9 / cl tebs dsryfnto / al h ae eto ucin 3 0 $Wde.rttp.eto.alti) .igtpooyedsrycl(hs; 3 1 } 3 }; 2 )

Conclusion
The widget factory is only one way of creating stateful plugins. There are a few different models that can be used and each have their own advantages and disadvantages. The widget factory solves lots of common problems for you and can greatly improve productivity, it also greatly improves code reuse, making it a great fit for jQuery UI as well as many other stateful plugins.

Exercises
jqfundamentals.com/book/index.html#chapter-1 83/111

5/18/12

jQuery Fundamentals

Make a Table Sortable


For this exercise, your task is to identify, download, and implement a table sorting plugin on the index.html page. When youre done, all columns in the table on the page should be sortable.

Write a Table-Striping Plugin


Open the file / x r i e / n e . t lin your browser. Use the eecssidxhm file / x r i e / s s r p . s Your task is to write a plugin eecssj/tiej. called "stripe" that you can call on any table element. When the plugin is called on a table element, it should change the color of odd rows in the table body to a user-specified color. 1 $'mTbe)srp(#ccc) (#yal'.tie'ccc'; Don't forget to return the table so other methods can be chained after the plugin!

Part III. Advanced Topics


This Section is a Work in Progress
Please visit http://github.com/rmurphey/jqfundamentals to contribute!

Back to top

Performance Best Practices


This chapter covers a number of jQuery and JavaScript best practices, in no particular order. Many of the best practices in this chapter are based on the jQuery Anti-Patterns for Performance presentation by Paul Irish.

jqfundamentals.com/book/index.html#chapter-1

84/111

5/18/12

jQuery Fundamentals

Cache length during loops


In a for loop, don't access the length property of an array every time; cache it beforehand. 1 vrmLnt =mArylnt; a yegh yra.egh 2 3 fr(a i=0 i<mLnt;i+ { o vr ; yegh +) 4 / d suf / o tf 5 }

Append new content outside of a loop


Touching the DOM comes at a cost; if you're adding a lot of elements to the DOM, do it all at once, not one at a time. 0 / ti i bd 1 / hs s a 0 $ec(yra,fnto(,ie){ 2 .ahmAry ucini tm 0 3 vrnwittm='l> +ie + a eLsIe <i' tm '/i' <l>; 0 4 $'bles)apn(eLsIe) (#alr'.pednwittm; 0 }; 5 ) 0 6 0 / bte:d ti 7 / etr o hs 0 vrfa = 8 a rg dcmn.raeouetrget) ouetcetDcmnFamn(; 0 9 1 $ec(yra,fnto(,ie){ 0 .ahmAry ucini tm 1 1 vrnwittm='l> +ie + a eLsIe <i' tm '/i' <l>; 1 2 fa.pedhl(eLsIe) rgapnCidnwittm; 1 }; 3 ) 1 $'bles)0.pedhl(rg; 4 (#alr'[]apnCidfa) 1 5 1 / o d ti 6 / r o hs 1 vrmHm ='; 7 a ytl ' 1 8 1 $ec(yra,fnto(,ie){ 9 .ahmAry ucini tm 2 0 hm + 'l> +ie +'/i' tl = <i' tm <l>; 2 }; 1 ) 2 $'bles)hm(ytl; 2 (#alr'.tlmHm)

Keep things DRY


Don't repeat yourself; if you're repeating yourself, you're doing it wrong. 0 / BD 1 / A 0 i (eetaedt(crety)! 2 f $vnfd.aa'urnl' = 'hwn' { soig) 0 3 $vnfd.tp) eetaeso(; 0 } 4 0 5 0 i (eetoe.aa'urnl' ! 6 f $vnhvrdt(crety) =
jqfundamentals.com/book/index.html#chapter-1 85/111

5/18/12

jQuery Fundamentals

'hwn' { soig) 0 7 $vnhvrso(; eetoe.tp) 0 } 8 0 9 1 i (sasdt(crety)! 'hwn' 0 f $pn.aa'urnl' = soig) { 1 1 $pn.tp) sasso(; 1 } 2 1 3 1 / GO! 4 / OD! 1 vr$lm =[eetae $vnhvr 5 a ees $vnfd, eetoe, $pn] sas; 1 $ec(ees fnto(,lm { 6 .ah$lm, uciniee) 1 7 i (lmdt(crety)! f ee.aa'urnl' = 'hwn' { soig) 1 8 ee.tp) lmso(; 1 9 } 2 }; 0 )

Beware anonymous functions


Anonymous functions bound everywhere are a pain. They're difficult to debug, maintain, test, or reuse. Instead, use an object literal to organize and name your handlers and callbacks. 0 / BD 1 / A 0 $dcmn)rayfnto( { 2 (ouet.ed(ucin) 0 3 $'mgc)cikfnto(){ (#ai'.lc(ucine 0 4 $'yyfet'.ldU(ucin) (#aefcs)siepfnto( { 0 5 / .. / . 0 6 }; ) 0 7 }; ) 0 8 0 9 $'hpies)la(r +' (#apns'.odul #ncrs,fnto( { uion' ucin) 1 0 / .. / . 1 1 }; ) 1 }; 2 ) 1 3 1 / BTE 4 / ETR 1 vrP ={ 5 a I 1 6 oRay:fnto( { ned ucin) 1 7 $'mgc)cikP.adMn; (#ai'.lc(Icnyt) 1 8 $'hpies)la(Iul+' (#apns'.odP.r #ncrs,P.ncrC) uion' Iuionb; 1 9 } , 2 0 2 1 cnyt :fnto(){ adMn ucine 2 2 $'yyfet'.ldU(Isieb; (#aefcs)siepP.ldC) 2 3 } , 2 4 2 5 sieb:fnto( {..} ldC ucin) . , 2 6 2 7 uionb:fnto( {..} ncrC ucin) . 2 } 8 ; 2 9 3 $dcmn)rayP.ned) 0 (ouet.ed(IoRay;

jqfundamentals.com/book/index.html#chapter-1

86/111

5/18/12

jQuery Fundamentals

Optimize Selectors
Selector optimization is less important than it used to be, as more browsers implement d c m n . u r S l c o A l )and ouetqeyeetrl( the burden of selection shifts from jQuery to the browser. However, there are still some tips to keep in mind.

ID-Based Selectors
Beginning your selector with an ID is always best. 1 2 3 4 5 / fs / at $'cnanrdvrbtr'; (#otie i.ooam) / sprfs / ue-at $'cnanr)fn(dvrbtr'; (#otie'.id'i.ooam)

The $ f . i dapproach is faster because the first selection is .nfn handled without going through the Sizzle selector engine IDonly selections are handled using d c m n . e E e e t y d ) ouetgtlmnBI(, which is extremely fast because it is native to the browser.

Specificity
Be specific on the right-hand side of your selector, and less specific on the left. 1 2 3 4 5 / uotmzd / npiie $'i.aa.ozlz) (dvdt gnae'; / otmzd / piie $'dt t.ozlz) (.aa dgnae';

Use t g c a sif possible on your right-most selector, and just a.ls


t gor a

just . l s on the left. cas

Avoid excessive specificity. 1 $'dt tbeatnest.ozlz) (.aa al.tede dgnae'; 2 3 / bte:do temdl i psil / etr rp h ide f osbe 4 $'dt t.ozlz) (.aa dgnae'; A "flatter" DOM also helps improve selector performance, as the selector engine has fewer layers to traverse when looking for an element.

Avoid the Universal Selector


Selections that specify or imply that a match could be found anywhere can be very slow. 1 $'btos>*) / eteeyepnie (.utn '; / xrml xesv 2 $'btos)cide(; / mc bte (.utn'.hlrn) / uh etr 3
jqfundamentals.com/book/index.html#chapter-1 87/111

5/18/12

jQuery Fundamentals

4 $'gne :ai'; / ipiduiesl (.edr rdo) / mle nvra slcin eeto 5 $'gne *rdo) / sm tig (.edr :ai'; / ae hn, epii nw xlct o 6 $'gne iptrdo) / mc bte (.edr nu:ai'; / uh etr

Use Event Delegation


Event delegation allows you to bind an event handler to one container element (for example, an unordered list) instead of multiple contained elements (for example, list items). jQuery makes this easy with $.fn.live and $.fn.delegate. Where possible, you should use $ f . e e a einstead of $ f . i e as it .ndlgt .nlv, eliminates the need for an unnecessary selection, and its explicit context (vs. $ f . i e context of d c m n ) reduces overhead . n l v 's ouet by approximately 80%. In addition to performance benefits, event delegation also allows you to add new contained elements to your page without having to re-bind the event handlers for them as they're added. 1 2 3 4 5 6 7 / bd(fteeaelt o ls ies / a i hr r os f it tm) $'itigr)cikhnlrn; (l.rge'.lc(adeF) / bte:eetdlgto wt $f.ie / etr vn eeain ih .nlv $'itigr)lv(cik,hnlrn; (l.rge'.ie'lc' adeF)

/ bs:eetdlgto wt / et vn eeain ih $f.eeae .ndlgt 8 / alw yut seiyacnetesl / los o o pcf otx aiy 9 $'mLs'.eeae'itigr, (#yit)dlgt(l.rge' 'lc' hnlrn; cik, adeF)

Detach Elements to Work With Them


The DOM is slow; you want to avoid manipulating it as much as possible. jQuery introduced $ f . e a hin version 1.4 to help .ndtc address this issue, allowing you to remove an element from the DOM while you work with it. 1 2 3 4 5 6 vr$al =$'mTbe) a tbe (#yal'; vr$aet=$al.aet) a prn tbeprn(; $al.eah) tbedtc(; / ..adlt adlt o rw t tbe / . d os n os f os o al $aetapn(tbe; prn.ped$al)

Use Stylesheets for Changing CSS on Many Elements


jqfundamentals.com/book/index.html#chapter-1 88/111

5/18/12

jQuery Fundamentals

If you're changing the CSS of more than 20 elements using $.fn.css, consider adding a style tag to the page instead for a nearly 60% increase in speed. 1 / fn fru t 2 eeet,so atr / ie o p o 0 lmns lw fe ta ht 2 $'.wdeg)cs'oo' 'ad2'; (asebr'.s(clr, #s13) 3 $'syetp=tx/s"asebr { (<tl ye"etcs>.wdeg clr:#s13}/tl>) oo ad2 <sye' 4 .pedo'ed) apnT(ha';

Use $ d t Instead of .aa


$f.aa .ndt
Using $.data on a DOM element instead of calling $.fn.data on a jQuery selection can be up to 10 times faster. Be sure you understand the difference between a DOM element and a jQuery selection before doing this, though. 1 2 3 4 5 / rglr / eua $ee)dt(e,au) (lm.aakyvle; / 1xfse / 0 atr $ aaee,e,au) dt(lmkyvle; .

Don't Act on Absent Elements


jQuery won't tell you if you're trying to run a whole lot of code on an empty selection it will proceed as though nothing's wrong. It's up to you to verify that your selection contains some elements. 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 / BD ti rn trefntos / A: hs us he ucin / bfr i raie teesntig / eoe t elzs hr' ohn / i teslcin / n h eeto $'nsctig)siep) (#ouhhn'.ldU(; / Bte / etr vr$yeeto =$'nsctig) a mSlcin (#ouhhn'; i (mSlcinlnt){ f $yeeto.egh $yeeto.ldU(;} mSlcinsiep) / BS:adadOc pui / ET d one lgn jur.ndOc =fnto(uc{ Qeyf.one ucinfn) ti.egh& fn.pl(hs; hslnt & ucapyti) rtr ti; eun hs } $ l.attm'.onefnto({ 'icries)dOc(ucin) ( / mk i aa!\/ / ae t jx o }; )

This guidance is especially applicable for jQuery UI widgets,


jqfundamentals.com/book/index.html#chapter-1 89/111

5/18/12

jQuery Fundamentals

which have a lot of overhead even when the selection doesn't contain elements.

Variable Definition
Variables can be defined in one statement instead of several. 1 2 3 4 5 6 7 8 9 / od&bse / l utd vrts =1 a et ; vrts2=fnto( {..} a et ucin) . ; vrts3=ts2ts) a et et(et; / nwhtes / e ons vrts =1 a et , ts2=fnto( {..} et ucin) . , ts3=ts2ts) et et(et;

In self-executing functions, variable definition can be skipped all together. 1 (ucinfo br {..}(,2; fnto(o, a) . )1 )

Conditionals
1 2 3 4 5 6 7 8 / odwy / l a i (ye= 'o'| tp = 'a' {..} f tp = fo | ye = br) . / bte / etr i (^fobr$.ettp) {..} f /(o|a)/ts(ye) . / ojc ltrllou / bet iea okp i ({fo:1 br:1}[ye){..} f ( o , a )tp] .

Don't Treat jQuery as a Black Box


Use the source as your documentation bookmark http://bit.ly/jqsource and refer to it often.

Back to top

Code Organization
Overview
jqfundamentals.com/book/index.html#chapter-1 90/111

5/18/12

jQuery Fundamentals

When you move beyond adding simple enhancements to your website with jQuery and start developing full-blown client-side applications, you need to consider how to organize your code. In this chapter, we'll take a look at various code organization patterns you can use in your jQuery application and explore the RequireJS dependency management and build system.

Key Concepts
Before we jump into code organization patterns, it's important to understand some concepts that are common to all good code organization patterns. Your code should be divided into units of functionality modules, services, etc. Avoid the temptation to have all of your code in one huge $ d c m n ) r a y )block. This (ouet.ed( concept, loosely, is known as encapsulation. Don't repeat yourself. Identify similarities among pieces of functionality, and use inheritance techniques to avoid repetitive code. Despite jQuery's DOM-centric nature, JavaScript applications are not all about the DOM. Remember that not all pieces of functionality need to or should have a DOM representation. Units of functionality should be loosely coupled a unit of functionality should be able to exist on its own, and communication between units should be handled via a messaging system such as custom events or pub/sub. Stay away from direct communication between units of functionality whenever possible. The concept of loose coupling can be especially troublesome to developers making their first foray into complex applications, so be mindful of this as you're getting started.

Encapsulation
The first step to code organization is separating pieces of your application into distinct pieces; sometimes, even just this effort is sufficient to lend

The Object Literal


An object literal is perhaps the simplest way to encapsulate related code. It doesn't offer any privacy for properties or methods, but it's useful for eliminating anonymous functions from your code, centralizing configuration options, and easing the path to reuse and refactoring.
Example 10.1: An object literal
jqfundamentals.com/book/index.html#chapter-1 91/111

5/18/12

jQuery Fundamentals

0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0

vrmFaue={ a yetr mPoet :'el' yrpry hlo, mMto :fnto( { yehd ucin) cnoelgmFauemPoet) osl.o(yetr.yrpry; } , ii :fnto(etns { nt ucinstig) mFauestig =stig; yetr.etns etns } , raStig :fnto( { edetns ucin) cnoelgmFauestig) osl.o(yetr.etns; } } ; mFauemPoet;/ 'el' yetr.yrpry / hlo mFauemMto(;/ lg 'el' yetr.yehd) / os hlo mFaueii( fo:'a'}; yetr.nt{ o br ) mFaueraStig(;/ lg {fo: yetr.edetns) / os o 'a'} br

The object literal above is simply an object assigned to a variable. The object has one property and several methods. All of the properties and methods are public, so any part of your application can see the properties and call methods on the object. While there is an init method, there's nothing requiring that it be called before the object is functional. How would we apply this pattern to jQuery code? Let's say that we had this code written in the traditional jQuery style: 0 / cikn o als ie lassm 1 / lcig n it tm od oe cnet otn 0 / uigtels ie' I adhds 2 / sn h it tms D n ie cnet otn 0 / i sbigls ies 3 / n iln it tm 0 $dcmn)rayfnto( { 4 (ouet.ed(ucin) 0 $'mFauel' 5 (#yetr i) 0 .ped'dv>) 6 apn(<i/' 0 .lc(ucin){ 7 cikfnto( 0 8 vr$hs=$ti) a ti (hs; 0 9 vr$i =$hsfn(dv) a dv ti.id'i'; 1 0 $i.od'o.h?tm'+ dvla(foppie= 1 1 $hsat(i', ti.tr'd) 1 2 fnto( { ucin) 1 3 $i.hw) dvso(; 1 4 $hssbig( ti.ilns) 1 5 .id'i'.ie) fn(dv)hd(; 1 6 } 1 7 ) ; 1 }; 8 ) 1 }; 9 ) If this were the extent of our application, leaving it as-is would be fine. On the other hand, if this was a piece of a larger application, we'd do well to keep this functionality separate from unrelated functionality. We might also want to move the URL out of the code and into a configuration area. Finally, we might want to break up the chain to make it easier to modify pieces of
jqfundamentals.com/book/index.html#chapter-1 92/111

5/18/12

jQuery Fundamentals

the functionality later.


Example 10.2: Using an object literal for a jQuery feature

0 vrmFaue={ 1 a yetr 0 ii :fnto(etns { 2 nt ucinstig) 0 3 mFauecni ={ yetr.ofg 0 4 $tm :$'mFauel', ies (#yetr i) 0 5 $otie :$'dv cnanr (<i cas"otie"<dv', ls=cnanr>/i>) 0 6 ulae:'foppie= rBs /o.h?tm' 0 7 } ; 0 8 0 9 / alwoerdn tedfutcni / lo vriig h eal ofg 1 0 $etn(yetr.ofg stig) .xedmFauecni, etns; 1 1 1 2 mFauestp) yetr.eu(; 1 } 3 , 1 4 1 stp:fnto( { 5 eu ucin) 1 6 mFauecni.ies yetr.ofg$tm 1 7 .ahmFauecetCnanr ec(yetr.raeotie) 1 8 .lc(yetr.hwtm; cikmFauesoIe) 1 } 9 , 2 0 2 cetCnanr:fnto( { 1 raeotie ucin) 2 2 vr$ =$ti) a i (hs, 2 3 $ = c mFauecni.cnanrcoe) yetr.ofg$otie.ln( 2 4 .pedo$) apnT(i; 2 5 2 6 $.aa'otie' $) idt(cnanr, c; 2 } 7 , 2 8 2 bidr :fnto( { 9 ulUl ucin) 3 0 rtr mFauecni.rBs + eun yetr.ofgulae 3 1 mFaue$urnIe.tr'd) yetr.crettmat(i'; 3 } 2 , 3 3 3 soIe :fnto( { 4 hwtm ucin) 3 5 vrmFaue$urnIe =$ti) a yetr.crettm (hs; 3 6 mFauegtotn(yetr.hwotn) yetr.eCnetmFauesoCnet; 3 } 7 , 3 8 3 gtotn :fnto(alak { 9 eCnet ucinclbc) 4 0 vrul=mFauebidr(; a r yetr.ulUl) 4 1 mFaue$urnIe yetr.crettm 4 2 .aa'otie'.odul dt(cnanr)la(r, clbc) alak; 4 } 3 , 4 4 4 soCnet:fnto( { 5 hwotn ucin) 4 6 mFaue$urnIe yetr.crettm 4 7 .aa'otie'.hw) dt(cnanr)so(; 4 8 mFauehdCnet) yetr.ieotn(; 4 } 9 , 5 0 5 hdCnet:fnto( { 1 ieotn ucin) 5 2 mFaue$urnIe.ilns) yetr.crettmsbig( 5 3 .ahfnto( { ec(ucin) 5 4 $ti)dt(cnanr)hd(; (hs.aa'otie'.ie) 5 5 }; ) 5 } 6
jqfundamentals.com/book/index.html#chapter-1 93/111

5/18/12

jQuery Fundamentals

5 } 7 ; 8 5 $dcmn)raymFaueii) 9 (ouet.ed(yetr.nt; The first thing you'll notice is that this approach is obviously far longer than the original again, if this were the extent of our application, using an object literal would likely be overkill. Assuming it's not the extent of our application, though, we've gained several things: We've broken our feature up into tiny methods. In the future, if we want to change how content is shown, it's clear where to change it. In the original code, this step is much harder to locate. We've eliminated the use of anonymous functions. We've moved configuration options out of the body of the code and put them in a central location. We've eliminated the constraints of the chain, making the code easier to refactor, remix, and rearrange. For non-trivial features, object literals are a clear improvement over a long stretch of code stuffed in a $(document).ready() block, as they get us thinking about the pieces of our functionality. However, they aren't a whole lot more advanced than simply having a bunch of function declarations inside of that $(document).ready() block.

The Module Pattern


The module pattern overcomes some of the limitations of the object literal, offering privacy for variables and functions while exposing a public API if desired.
Example 10.3: The module pattern

0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0

vrfaue=fnto( { a etr (ucin) / piaevralsadfntos / rvt aibe n ucin vrpiaehn ='ert, a rvtTig sce' pbiTig='o sce' ulchn nt ert, cagPiaehn =fnto( { hnervtTig ucin) piaehn ='ue sce' rvtTig spr ert; } , syrvtTig=fnto( { aPiaehn ucin) cnoelgpiaehn) osl.o(rvtTig; cagPiaehn(; hnervtTig) } ; / pbi AI / ulc P rtr { eun pbiTig:pbiTig ulchn ulchn, syrvtTig:syrvtTig aPiaehn aPiaehn }
94/111

jqfundamentals.com/book/index.html#chapter-1

5/18/12

jQuery Fundamentals

2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8

}(; )) fauepbiTig / 'o sce' etr.ulchn; / nt ert fauesyrvtTig) etr.aPiaehn(; / lg 'ert adcagstevle / os sce' n hne h au / o piaehn / f rvtTig

In the example above, we self-execute an anonymous function that returns an object. Inside of the function, we define some variables. Because the variables are defined inside of the function, we don't have access to them outside of the function unless we put them in the return object. This means that no code outside of the function has access to the p i a e h n variable rvtTig or to the c a g P i a e h n function. However, hnervtTig s y r v t T i gdoes have access to p i a e h n and aPiaehn rvtTig
c a g P i a e h n , because hnervtTig

both were defined in the same

scope as s y r v t T i g aPiaehn. This pattern is powerful because, as you can gather from the variable names, it can give you private variables and functions while exposing a limited API consisting of the returned object's properties and methods. Below is a revised version of the previous example, showing how we could create the same feature using the module pattern while only exposing one public method of the module, soIeBIdx) hwtmyne(.
Example 10.4: Using the module pattern for a jQuery feature

0 $dcmn)rayfnto( { 1 (ouet.ed(ucin) 0 vrfaue=(ucin){ 2 a etr fnto( 0 3 0 4 vr$tm =$'mFauel', a ies (#yetr i) 0 5 $otie =$'dv cnanr (<i cas"otie"<dv', ls=cnanr>/i>) 0 6 $urnIe, crettm 0 7 0 8 ulae='foppie=, rBs /o.h?tm' 0 9 1 0 cetCnanr=fnto( { raeotie ucin) 1 1 vr$ =$ti) a i (hs, 1 2 $ = c $otie.ln(.pedo$) cnanrcoe)apnT(i; 1 3 1 4 $.aa'otie' $) idt(cnanr, c; 1 5 } , 1 6 1 7 bidr =fnto( { ulUl ucin) 1 8 rtr ulae+ eun rBs $urnIe.tr'd) crettmat(i'; 1 9 } , 2 0 2 1 2 2 2 3
jqfundamentals.com/book/index.html#chapter-1

soIe =fnto( { hwtm ucin) vr$urnIe =$ti) a crettm (hs; gtotn(hwotn) eCnetsoCnet;
95/111

5/18/12

jQuery Fundamentals

2 4 2 5 2 6 2 7

} ,

soIeBIdx=fnto(d){ hwtmyne ucinix $poysoIe, .rx(hwtm $tm.e(d); iesgtix) 2 8 } , 2 9 3 0 gtotn =fnto(alak { eCnet ucinclbc) 3 1 $urnIe.aa'otie'.odbidr(, crettmdt(cnanr)la(ulUl) clbc) alak; 3 2 } , 3 3 3 4 soCnet=fnto( { hwotn ucin) 3 5 $urnIe.aa'otie'.hw) crettmdt(cnanr)so(; 3 6 hdCnet) ieotn(; 3 7 } , 3 8 3 9 hdCnet=fnto( { ieotn ucin) 4 0 $urnIe.ilns) crettmsbig( 4 1 .ahfnto( { ec(ucin) 4 2 $ti)dt(cnanr)hd(; (hs.aa'otie'.ie) 4 3 }; ) 4 4 } ; 4 5 4 6 $tm ies 4 7 .ahcetCnanr ec(raeotie) 4 8 .lc(hwtm; ciksoIe) 4 9 5 0 rtr {soIeBIdx: eun hwtmyne soIeBIdx} hwtmyne ; 5 }(; 1 )) 5 2 5 fauesoIeBIdx0; 3 etr.hwtmyne() 5 }; 4 )

Managing Dependencies
Note
This section is based heavily on the excellent RequireJS documentation at http://requirejs.org/docs/jquery.html, and is used with the permission of RequireJS author James Burke.

When a project reaches a certain size, managing the script modules for a project starts to get tricky. You need to be sure to sequence the scripts in the right order, and you need to start seriously thinking about combining scripts together into a bundle for deployment, so that only one or a very small number of requests are made to load the scripts. You may also want to load code on the fly, after page load. RequireJS, a dependency management tool by James Burke, can help you manage the script modules, load them in the right order, and make it easy to combine the scripts later via the
jqfundamentals.com/book/index.html#chapter-1 96/111

5/18/12

jQuery Fundamentals

RequireJS optimization tool without needing to change your markup. It also gives you an easy way to load scripts after the page has loaded, allowing you to spread out the download size over time. RequireJS has a module system that lets you define well-scoped modules, but you do not have to follow that system to get the benefits of dependency management and build-time optimizations. Over time, if you start to create more modular code that needs to be reused in a few places, the module format for RequireJS makes it easy to write encapsulated code that can be loaded on the fly. It can grow with you, particularly if you want to incorporate internationalization (i18n) string bundles, to localize your project for different languages, or load some HTML strings and make sure those strings are available before executing code, or even use JSONP services as dependencies.

Getting RequireJS
The easiest way to use RequireJS with jQuery is to download a build of jQuery that has RequireJS built in. This build excludes portions of RequireJS that duplicate jQuery functionality. You may also find it useful to download a sample jQuery project that uses RequireJS.

Using RequireJS with jQuery


Using RequireJS in your page is simple: just include the jQuery that has RequireJS built in, then require your application files. The following example assumes that the jQuery build, and your other scripts, are all in a s r p s directory. cit/
Example 10.5: Using RequireJS: A simple example

0 <DCYEhm> 1 !OTP tl 0 <tl 2 hm> 0 <ed 3 ha> 0 4 <il>QeyRqieSSml ttejur+eurJ ape Pg<tte ae/il> 0 5 <citsc"cit/eursrp r=srpsrqie jur.s>/cit qeyj"<srp> 0 6 <citrqie[ap];/cit srp>eur("p")<srp> 0 <ha> 7 /ed 0 <oy 8 bd> 0 9 <1jur+eurJ Sml Pg<h> h>QeyRqieS ape ae/1 1 <bd> 0 /oy 1 <hm> 1 /tl The call to r q i e [ a p ] tells RequireJS to load the eur("p") s r p s a p j file. RequireJS will load any dependency that is cit/p.s passed to r q i e )without a . sextension from the same eur( j directory as r q i e j u r . s though this can be configured to eur-qeyj, behave differently. If you feel more comfortable specifying the whole path, you can also do the following:
jqfundamentals.com/book/index.html#chapter-1 97/111

5/18/12

jQuery Fundamentals

1 <citrqie[srpsapj") srp>eur("cit/p.s]; <srp> /cit What is in a p j ? Another call to r q i e j to load all the p.s eur.s scripts you need and any init work you want to do for the page. This example a p j script loads two plugins, j u r . l h . s p.s qeyapaj and j u r . e a j (not the names of real plugins, just an qeybt.s example). The plugins should be in the same directory as rqiejur.s eur-qeyj:
Example 10.6: A simple JavaScript file with dependencies

1 rqie[jur.lh" "qeybt", eur("qeyapa, jur.ea] fnto( { ucin) 2 /tejur.lh.sadjur.eaj /h qeyapaj n qeybt.s puishv be lae. lgn ae en odd 3 $fnto( { (ucin) 4 $'oy)apa)bt(; (bd'.lh(.ea) 5 }; ) 6 }; )

Creating Reusable Modules with RequireJS


RequireJS makes it easy to define reusable modules via r q i e d f ) A RequireJS module can have dependencies that eur.e(. can be used to define a module, and a RequireJS module can return a value an object, a function, whatever that can then be consumed by yet other modules. If your module does not have any dependencies, then just specify the name of the module as the first argument to r q i e d f ) The second argument is just an object literal that eur.e(. defines the module's properties. For example:
Example 10.7: Defining a RequireJS module that has no dependencies

1 2 3 4 5 6

rqiedf"ysmlsit, eur.e(m/ipehr" { clr "lc" oo: bak, sz:"nsz" ie uiie } ) ;

This example would be stored in a my/simpleshirt.js file. If your module has dependencies, you can specify the dependencies as the second argument to r q i e d f )(as an eur.e( array) and then pass a function as the third argument. The function will be called to define the module once all dependencies have loaded. The function receives the values returned by the dependencies as its arguments (in the same order they were required in the array), and the function should return an object that defines the module.
Example 10.8: Defining a RequireJS module with dependencies
jqfundamentals.com/book/index.html#chapter-1 98/111

5/18/12

jQuery Fundamentals

0 rqiedf"ysit, 1 eur.e(m/hr" 0 [m/at,"yivnoy] 2 "ycr" m/netr", 0 fnto(at ivnoy { 3 ucincr, netr) 0 4 /rtr a ojc t dfn te /eun n bet o eie h "ysit mdl. m/hr" oue 0 5 rtr { eun 0 6 clr "le, oo: bu" 0 7 sz:"ag" ie lre 0 8 adoat fnto( { dTCr: ucin) 0 9 ivnoydceetti) netr.ermn(hs; 1 0 cr.d(hs; atadti) 1 1 } 1 2 } 1 } 3 1 ) 4 ; In this example, a my/shirt module is created. It depends on my/cart and my/inventory. On disk, the files are structured like this: 1 m/atj ycr.s 2 m/netr.s yivnoyj 3 m/hr.s ysitj The function that defines m / h r is not called until the m / a t ysit ycr and m / n e t r modules have been loaded, and the function yivnoy receives the modules as the c r and i v n o yarguments. The at netr order of the function arguments must match the order in which the dependencies were required in the dependencies array. The object returned by the function call defines the m / h r module. ysit Be defining modules in this way, m / h r does not exist as a ysit global object. Modules that define globals are explicitly discouraged, so multiple versions of a module can exist in a page at a time. Modules do not have to return objects; any valid return value from a function is allowed.
Example 10.9: Defining a RequireJS module that returns a function

0 rqiedf"ytte, 1 eur.e(m/il" 0 [m/eedny" "ydpnec2] 2 "ydpnec1, m/eedny", 0 fnto(e1 dp){ 3 ucindp, e2 0 4 /rtr afnto t dfn /eun ucin o eie "ytte.I gt o st m/il" t es r es 0 5 /tewno tte /h idw il. 0 6 rtr fnto(il){ eun ucintte 0 7 rtr tte?(idwtte= eun il wno.il tte :wno.il; il) idwtte 0 8 } 0 } 9 1 ) 0 ; Only one module should be required per JavaScript file.

jqfundamentals.com/book/index.html#chapter-1

99/111

5/18/12

jQuery Fundamentals

Optimizing Your Code: The RequireJS Build Tool


Once you incorporate RequireJS for dependency management, your page is set up to be optimized very easily. Download the RequireJS source and place it anywhere you like, preferrably somewhere outside your web development area. For the purposes of this example, the RequireJS source is placed as a sibling to the w b p directory, which contains the HTML page eap and the scripts directory with all the scripts. Complete directory structure: 1 2 3 4 5 6 rqies (sdfrtebidtos eurj/ ue o h ul ol) wbp/p.tl eapaphm wbp/cit/p.s eapsrpsapj wbp/cit/eur-qeyj eapsrpsrqiejur.s wbp/cit/qeyapaj eapsrpsjur.lh.s wbp/cit/qeybt.s eapsrpsjur.eaj

Then, in the scripts directory that has r q i e j u r . sand eur-qeyj app.js, create a file called app.build.js with the following contents:
A RequireJS build configuration file

0 1 0 2 0 3 0 4 0 5 0 6

{ api:"." pDr ./, bsUl "cit/, aer: srps" dr "../eapbid, i: ./.wbp-ul" /Cmetotteotmz ln i yuwn /omn u h piie ie f o at /tecd mnfe b CoueCmie /h oe iiid y lsr oplr uig sn 0 /te"ipe otmztosmd 7 /h sml" piiain oe 0 otmz:"oe, 8 piie nn" 0 9 1 mdls [ 0 oue: 1 1 { 1 2 nm:"p" ae ap 1 3 } 1 ] 4 1 } 5 To use the build tool, you need Java 6 installed. Closure Compiler is used for the JavaScript minification step (if o t m z : " o e is commented out), and it requires Java 6. piie nn" To start the build, go to the webapp/scripts directory, execute the following command: 1 2 3 4 5 #nnwnossses o-idw ytm ./.rqiesbidbids apbidj ../eurj/ul/ul.h p.ul.s #wnossses idw ytm .\.rqiesbidbidbt ..\eurj\ul\ul.a apbidj p.ul.s

Now, in the webapp-build directory, a p j will have the a p j p.s p.s contents, j u r . l h . sand j u r . e a j inlined. If you qeyapaj qeybt.s then load the a p h m file in the w b p - u l directory, you p.tl eapbid
jqfundamentals.com/book/index.html#chapter-1 100/111

5/18/12

jQuery Fundamentals

should not see any network requests for j u r . l h . sand qeyapaj


jur.eaj. qeybt.s

Exercises
Create a Portlet Module
Open the file / x r i e / o t e s h m in your browser. Use eecssprlt.tl the file / x r i e / s p r l t . s Your task is to create a eecssj/otesj. portlet creation function that uses the module pattern, such that the following code will work: 1 2 3 4 5 6 7 vrmPrlt=Prlt{ a yote ote( tte:'ur' il Cry, suc :'aahm/ur.tl, ore dt/tlcryhm' iiiltt :'pn / o 'lsd ntaSae oe' / r coe' }; ) mPrlt$lmn.pedo'oy) yote.eeetapnT(bd';

Each portlet should be a div with a title, a content area, a button to open/close the portlet, a button to remove the portlet, and a button to refresh the portlet. The portlet returned by the Portlet function should have the following public API: 1 mPrltoe(;/ freoe sae yote.pn) / oc pn tt 2 mPrltcoe) / frecoesae yote.ls(; / oc ls tt 3 mPrlttgl(;/ tgl oe/ls yote.oge) / oge pncoe sae tt 4 mPrltrfeh) / rfehtecnet yote.ers(; / ers h otn 5 mPrltdsry) / rmv teprlt yote.eto(; / eoe h ote fo tepg rm h ae 6 mPrltstore'aahm/noshm'; yote.eSuc(dt/tloin.tl) 7 / cag tesuc / hne h ore

Back to top

Custom Events
Introducing Custom Events
Were all familiar with the basic events click, mouseover, focus, blur, submit, etc. that we can latch on to as a user interacts with the browser. Custom events open up a whole new world of event-driven programming. In this chapter, well use jQuerys custom events system to make a simple Twitter search application. It can be difficult at first to understand why you'd want to use custom events, when the built-in events seem to suit your needs
jqfundamentals.com/book/index.html#chapter-1 101/111

5/18/12

jQuery Fundamentals

just fine. It turns out that custom events offer a whole new way of thinking about event-driven JavaScript. Instead of focusing on the element that triggers an action, custom events put the spotlight on the element being acted upon. This brings a bevy of benefits, including: Behaviors of the target element can easily be triggered by different elements using the same code. Behaviors can be triggered across multiple, similar, target elements at once. Behaviors are more clearly associated with the target element in code, making code easier to read and maintain. Why should you care? An example is probably the best way to explain. Suppose you have a lightbulb in a room in a house. The lightbulb is currently turned on, and its controlled by two threeway switches and a clapper: 1 <i cas"om i=kthn> dv ls=ro" d"ice" 2 <i cas"ihbl o"<dv dv ls=lgtub n>/i> 3 <i cas"wth>/i> dv ls=sic"<dv 4 <i cas"wth>/i> dv ls=sic"<dv 5 <i cas"lpe"<dv dv ls=capr>/i> 6 <dv /i> Triggering the clapper or either of the switches will change the state of the lightbulb. The switches and the clapper dont care what state the lightbulb is in; they just want to change the state. Without custom events, you might write some code like this: 1 $'sic,.lpe'.lc(ucin){ (.wth capr)cikfnto( 2 vr$ih = a lgt $ti)prn(.id'lgtub) (hs.aet)fn(.ihbl'; 3 i (lgthsls(o'){ f $ih.aCas'n) 4 $ih.eoels(o'.dCas'f'; lgtrmvCas'n)adls(of) 5 }es { le 6 $ih.eoels(of)adls(o'; lgtrmvCas'f'.dCas'n) 7 } 8 }; ) With custom events, your code might look more like this: 0 $'lgtub)bn(cagSae, 1 (.ihbl'.id'hnett' fnto(){ ucine 0 2 vr$ih =$ti) a lgt (hs; 0 3 i (lgthsls(o'){ f $ih.aCas'n) 0 4 $ih.eoels(o'.dCas'f'; lgtrmvCas'n)adls(of) 0 5 }es { le 0 6 $ih.eoels(of)adls(o'; lgtrmvCas'f'.dCas'n) 0 7 } 0 }; 8 ) 0 9 1 $'sic,.lpe'.lc(ucin){ 0 (.wth capr)cikfnto( 1 1 $ti)prn(.id'lgtub)tigr'hnett'; (hs.aet)fn(.ihbl'.rge(cagSae) 1 }; 2 )
jqfundamentals.com/book/index.html#chapter-1 102/111

5/18/12

jQuery Fundamentals

This last bit of code is not that exciting, but something important has happened: weve moved the behavior of the lightbulb to the lightbulb, and away from the switches and the clapper. Lets make our example a little more interesting. Well add another room to our house, along with a master switch, as shown here: 0 <i cas"om i=kthn> 1 dv ls=ro" d"ice" 0 2 <i cas"ihbl o"<dv dv ls=lgtub n>/i> 0 3 <i cas"wth>/i> dv ls=sic"<dv 0 4 <i cas"wth>/i> dv ls=sic"<dv 0 5 <i cas"lpe"<dv dv ls=capr>/i> 0 6 0 7 0 8 0 9 1 0 1 1 1 2 1 3 <dv /i> <i cas"om i=bdom> dv ls=ro" d"ero" <i cas"ihbl o"<dv dv ls=lgtub n>/i> <i cas"wth>/i> dv ls=sic"<dv <i cas"wth>/i> dv ls=sic"<dv <i cas"lpe"<dv dv ls=capr>/i> <dv /i> <i i=mse_wth>/i> dv d"atrsic"<dv

If there are any lights on in the house, we want the master switch to turn all the lights off; otherwise, we want it to turn all lights on. To accomplish this, well add two more custom events to the lightbulbs: t r O and t r O f Well make use of them in unn unf. the c a g S a ecustom event, and use some logic to decide hnett which one the master switch should trigger: 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 $'lgtub) (.ihbl' .id'hnett' fnto(){ bn(cagSae, ucine vr$ih =$ti) a lgt (hs; i (lgthsls(o'){ f $ih.aCas'n) $ih.rge(trOf) lgttigr'unf'; }es { le $ih.rge(trO'; lgttigr'unn) } } ) .id'unn,fnto(){ bn(trO' ucine $ti)rmvCas'f'.dCas'n) (hs.eoels(of)adls(o'; } ) .id'unf' fnto(){ bn(trOf, ucine $ti)rmvCas'f'.dCas'n) (hs.eoels(of)adls(o'; }; ) $'sic,.lpe'.lc(ucin){ (.wth capr)cikfnto( $ti)prn(.id'lgtub)tigr'hnett'; (hs.aet)fn(.ihbl'.rge(cagSae) }; ) $'mse_wth)cikfnto( { (#atrsic'.lc(ucin) i ((.ihbl.n)lnt){ f $'lgtubo'.egh $'lgtub)tigr'unf'; (.ihbl'.rge(trOf) }es { le $'lgtub)tigr'unn) (.ihbl'.rge(trO'; } }; )

Note how the behavior of the master switch is attached to the master switch; the behavior of a lightbulb belongs to the
jqfundamentals.com/book/index.html#chapter-1 103/111

5/18/12

jQuery Fundamentals

lightbulbs.

Note
If youre accustomed to object-oriented programming, you may find it useful to think of custom events as methods of objects. Loosely speaking, the object to which the method belongs is created via the jQuery selector. Binding the changeState custom event to all $ l g t )elements is (.ih akin to having a class called L g twith a method of ih
c a g S a e and then instantiating new L g tobjects hnett, ih

for

each element with a classname of light.

Recap: $.fn.bind and $.fn.trigger In the world of custom events, there are two important jQuery methods: $ f . i dand $ f . r g e . In the Events chapter, .nbn .ntigr we saw how to use these methods for working with user events; for this chapter, it's important to remember two things: The $ f . i dmethod takes an event type and an event .nbn handling function as arguments. Optionally, it can also receive event-related data as its second argument, pushing the event handling function to the third argument. Any data that is passed will be available to the event handling function in the d t property of the event object. The aa event handling function always receives the event object as its first argument. The $ f . r g e method takes an event type as its .ntigr argument. Optionally, it can also take an array of values. These values will be passed to the event handling function as arguments after the event object. Here is an example of the usage of $ f . i dand $ f . r g e .nbn .ntigr that uses custom data in both cases: 1 $dcmn)bn(mCsoEet,{fo: (ouet.id'yutmvn' o 'a'} fnto(,ag,ag){ br , ucine r1 r2 2 cnoelgedt.o) / 'a' osl.o(.aafo; / br 3 cnoelgag) / 'i' osl.o(r1; / bm 4 cnoelgag) / 'a' osl.o(r2; / bz 5 }; ) 6 7 $dcmn)tigr'yutmvn' [ (ouet.rge(mCsoEet, 'i' 'a']; bm, bz )

A Sample Application
To demonstrate the power of custom events, were going to create a simple tool for searching Twitter. The tool will offer several ways for a user to add search terms to the display: by entering a search term in a text box, by entering multiple search terms in the URL, and by querying Twitter for trending terms.
jqfundamentals.com/book/index.html#chapter-1 104/111

5/18/12

jQuery Fundamentals

The results for each term will be shown in a results container; these containers will be able to be expanded, collapsed, refreshed, and removed, either individually or all at once. When were done, it will look like this: Figure 11.1. Our finished application

The Setup Well start with some basic HTML: 0 <1TitrSac<h> 1 h>wte erh/1 0 <nu tp=bto"i=gtted" 2 ipt ye"utn d"e_rns 0 3 vle"odTedn Trs / au=La rnig em" > 0 4 0 <om 5 fr> 0 6 <nu tp=tx"cas"nu_et ipt ye"et ls=ipttx" 0 7 i=sac_em / d"erhtr" > 0 8 <nu tp=sbi" ipt ye"umt
jqfundamentals.com/book/index.html#chapter-1 105/111

5/18/12

jQuery Fundamentals

cas"nu_umt ls=iptsbi" 0 9 vle"d Sac Tr"/ au=Ad erh em > 1 <fr> 0 /om 1 1 1 <i i=titr> 2 dv d"wte" 1 3 <i cas"epaersls> dv ls=tmlt eut" 1 4 <2Sac Rslsfr h>erh eut o 1 5 <pncas"erhtr"<sa> sa ls=sac_em>/pn <h> /2 1 6 <dv /i> 1 <dv 7 /i> This gives us a container (#twitter) for our widget, a template for our results containers (hidden via CSS), and a simple form where users can input a search term. (For the sake of simplicity, were going to assume that our application is JavaScript-only and that our users will always have CSS.) There are two types of objects well want to act on: the results containers, and the Twitter container. The results containers are the heart of the application. Well create a plugin that will prepare each results container once its added to the Twitter container. Among other things, it will bind the custom events for each container and add the action buttons at the top right of each container. Each results container will have the following custom events: refresh Mark the container as being in the refreshing state, and fire the request to fetch the data for the search term. populate Receive the returned JSON data and use it to populate the container. remove Remove the container from the page after the user verifies the request to do so. Verification can be bypassed by passing true as the second argument to the event handler. The remove event also removes the term associated with the results container from the global object containing the search terms. collapse Add a class of collapsed to the container, which will hide the results via CSS. It will also turn the containers Collapse button into an Expand button. expand Remove the collapsed class from the container. It will also
jqfundamentals.com/book/index.html#chapter-1 106/111

5/18/12

jQuery Fundamentals

turn the containers Expand button into a Collapse button. The plugin is also responsible for adding the action buttons to the container. It binds a click event to each actions list item, and uses the list items class to determine which custom event will be triggered on the corresponding results container. 01 $f.wteRsl =fnto(etns { 0 .ntitreut ucinstig) 02 0 rtr ti.ahfnto( { eun hsec(ucin) 03 0 vr$eut =$ti) a rsls (hs, 04 0 $cin = atos $f.wteRsl.cin = .ntitreutatos 05 0 $f.wteRsl.cin .ntitreutatos | | 06 0 $f.wteRsl.raecin(, .ntitreutcetAtos) 07 0 $ = a $cin.ln(.rpnT(rsls, atoscoe)peedo$eut) 08 0 tr =stig.em em etnstr; 09 0 00 1 $eut.id'pnsac_em)tx(em; rslsfn(sa.erhtr'.ettr) 01 1 02 1 $ec( .ah 03 1 [rfeh,'ouae, 'ers' pplt' 'eoe,'olpe,'xad] rmv' clas' epn', 04 1 fnto(,e){ ucini v 05 1 $eut.id rslsbn( 06 1 e, v 07 1 {tr :tr } em em , 08 1 $f.wteRsl.vnse] .ntitreuteet[v 09 1 ) ; 00 2 } 01 2 ) ; 02 2 03 2 / uetecaso ec ato t / s h ls f ah cin o fgr ot iue u 04 2 / wiheeti wl tigro / hc vn t il rge n terslspnl h eut ae 05 2 $.id'i)cikfnto( { afn(l'.lc(ucin) 06 2 / ps tel ta wscikd / as h i ht a lce t tefnto o h ucin 07 2 / s i cnb mnpltdi / o t a e aiuae f nee edd 08 2 $eut.rge((hs.tr'ls', rslstigr$ti)at(cas) [$ti)]; (hs ) 09 2 }; ) 00 3 }; ) 01 } 3 ; 02 3 03 $f.wteRsl.raecin = 3 .ntitreutcetAtos fnto( { ucin) 04 3 rtr $'u cas"cin" eun (<l ls=atos /'.ped >)apn( 05 3 'l cas"ers"Rfeh/i' <i ls=rfeh>ers<l> + 06 3 'l cas"eoe>eoe/i'+ <i ls=rmv"Rmv<l> 07 3 'l <i cas"olpe>olpe/i' ls=clas"Clas<l> 08 3 ) ; 09 } 3 ; 00 4 01 $f.wteRsl.vns={ 4 .ntitreuteet 02 4 rfeh:fnto(){ ers ucine
jqfundamentals.com/book/index.html#chapter-1 107/111

5/18/12

jQuery Fundamentals

03 4

/ idct ta terslsae / niae ht h eut r rfehn ersig 04 4 vr$hs= a ti $ti)adls(rfehn'; (hs.dCas'ersig) 05 4 06 4 $hsfn(ptet)rmv(; ti.id'.we'.eoe) 07 4 $eut.ped'p rslsapn(< cas"odn"Laig../>) ls=laig>odn .<p'; 08 4 09 4 / gttetitrdt uigjop / e h wte aa sn sn 00 5 $gtSN .eJO( 01 5 'tp/sac.wte.o/erhjo? ht:/erhtitrcmsac.sn q'+ = 02 5 ecp(.aatr)+ saeedt.em 'rp5clbc=' &p=&alak?, 03 5 fnto(sn { ucinjo) 04 5 $hstigr'ouae,[ ti.rge(pplt' jo ]; sn ) 05 5 } 06 5 ) ; 07 5 } , 08 5 09 5 pplt :fnto(,jo){ ouae ucine sn 00 6 vrrsls=jo.eut; a eut snrsls 01 6 vr$hs=$ti) a ti (hs; 02 6 03 6 $hsfn(plaig)rmv(; ti.id'.odn'.eoe) 04 6 05 6 $ec(eut,fnto(,eut .ahrsls ucinirsl) { 06 6 vrtet='pcas"we"' a we < ls=tet> + 07 6 'a < he=ht:/wte.o/ + rf"tp/titrcm' 08 6 rsl.rmue + eutfo_sr 09 6 '> + "' 00 7 rsl.rmue + eutfo_sr 01 7 '/> '+ <a: 02 7 rsl.et+ euttx 03 7 '<pncas"ae> + sa ls=dt"' 04 7 rsl.rae_t+ eutcetda 05 7 '/pn'+ <sa> 06 7 '/>; <p' 07 7 $hsapn(we) ti.pedtet; 08 7 }; ) 09 7 00 8 / idct ta tersls / niae ht h eut 01 8 / aedn rfehn / r oe ersig 02 8 $hsrmvCas'ersig) ti.eoels(rfehn'; 03 8 } , 04 8 05 8 rmv :fnto(,fre { eoe ucine oc) 06 8 i ( f 07 8 !oc & fre & 08 8 !ofr(Rmv pnlfrtr cnim'eoe ae o em '+edt.em+'' .aatr ?) 09 8 ){ 00 9 rtr; eun 01 9 } 02 9 $ti)rmv(; (hs.eoe) 03 9 04 9 / idct ta w n lne / niae ht e o ogr 05 9 / hv apnlfrtetr / ae ae o h em 06 9 sac_em[.aatr]=0 erhtrsedt.em ; 07 9 } ,
jqfundamentals.com/book/index.html#chapter-1 108/111

5/18/12

jQuery Fundamentals

08 9 09 9 10 0 11 0 12 0 13 0 14 0 15 0 16 0 17 0 18 0 19 0 10 1 11 1 12 } 1 ;

clas :fnto(){ olpe ucine $ti)fn(l.olpe)rmvCas'olpe) (hs.id'iclas'.eoels(clas' .dCas'xad)tx(Epn'; adls(epn'.et'xad) } , $ti)adls(clasd) (hs.dCas'olpe';

epn :fnto(){ xad ucine $ti)fn(l.xad)rmvCas'xad) (hs.id'iepn'.eoels(epn' .dCas'olpe)tx(Clas'; adls(clas'.et'olpe) } $ti)rmvCas'olpe'; (hs.eoels(clasd)

The Twitter container itself will have just two custom events: getResults Receives a search term and checks to determine whether theres already a results container for the term; if not, adds a results container using the results template, set up the results container using the $ f . w t e R s l plugin .ntitreut discussed above, and then triggers the r f e hevent on ers the results container in order to actually load the results. Finally, it will store the search term so the application knows not to re-fetch the term. getTrends Queries Twitter for the top 10 trending terms, then iterates over them and triggers the g t e u t event for eRsls each of them, thereby adding a results container for each term. Here's how the Twitter container bindings look: 0 $'titr) 1 (#wte' 0 2 .id'eRsls,fnto(,tr){ bn(gteut' ucine em 0 3 / mk sr w dnthv abx / ae ue e o' ae o frti tr aray o hs em led 0 4 i (sac_em[em){ f !erhtrstr] 0 5 vr$hs=$ti) a ti (hs; 0 6 vr$epae= a tmlt $hsfn(dvtmlt'; ti.id'i.epae) 0 7 0 8 / mk acp o tetmlt / ae oy f h epae dv i 0 9 / adisr i a tefrt / n net t s h is rslsbx eut o 1 0 $eut =$epaecoe) rsls tmlt.ln(. 1 1 rmvCas'epae) eoels(tmlt'. 1 2 isrBfr(ti.id'i:is') neteoe$hsfn(dvfrt). 1 3 titreut{ wteRsl( 1 4 'em :tr tr' em 1 5 }; ) 1 6 1 7 / la tecnetuigte / od h otn sn h "ers" rfeh
jqfundamentals.com/book/index.html#chapter-1 109/111

5/18/12

jQuery Fundamentals

1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1

/ cso eetta w bud / utm vn ht e on t terslscnanr o h eut otie $eut.rge(rfeh) rslstigr'ers'; sac_em[em =1 erhtrstr] ; } } ) .id'eTed' fnto(){ bn(gtrns, ucine vr$hs=$ti) a ti (hs; $gtSN'tp/sac.wte.o/rnsjo? .eJO(ht:/erhtitrcmted.sn clbc=' fnto(sn { alak?, ucinjo) vrted =jo.rns a rns snted; $ec(rns fnto(, .ahted, ucini ted { rn) $hstigr'eRsls, ti.rge(gteut' [tednm ]; rn.ae ) }; ) }; ) }; )

So far, weve written a lot of code that does approximately nothing, but thats OK. By specifying all the behaviors that we want our core objects to have, weve created a solid framework for rapidly building out the interface. Lets start by hooking up our text input and the Load Trending Terms button. For the text input, well capture the term that was entered in the input and pass it as we trigger the Twitter containers g t e u t event. Clicking the Load Trending eRsls Terms will trigger the Twitter containers g t r n sevent: eTed 1 $'om)sbi(ucine { (fr'.umtfnto() 2 epeeteal(; .rvnDfut) 3 vrtr =$'sac_em)vl) a em (#erhtr'.a(; 4 $'titr)tigr'eRsls,[ (#wte'.rge(gteut' tr ]; em ) 5 }; ) 6 7 $'gtted'.lc(ucin){ (#e_rns)cikfnto( 8 $'titr)tigr'eTed'; (#wte'.rge(gtrns) 9 }; ) By adding a few buttons with the appropriate IDs, we can make it possible to remove, collapse, expand, and refresh all results containers at once, as shown below. For the remove button, note how were passing a value of true to the event handler as its second argument, telling the event handler that we dont want to verify the removal of individual containers. 1 $ec('ers' 'xad,'olpe] .ah[rfeh, epn' clas', fnto(,e){ ucini v 2 $''+e)cikfnto(){ (# v.lc(ucine $'titrdvrsls)tigre) }; (#wte i.eut'.rge(v; ) 3 }; ) 4 5 $'rmv'.lc(ucine { (#eoe)cikfnto() 6 i (ofr(Rmv alrsls'){ f cnim'eoe l eut?) 7 $'titr (#wte dvrsls)tigr'eoe,[tu ]; i.eut'.rge(rmv' re ) 8 } 9 }; )
jqfundamentals.com/book/index.html#chapter-1 110/111

5/18/12

jQuery Fundamentals

Conclusion Custom events offer a new way of thinking about your code: they put the emphasis on the target of a behavior, not on the element that triggers it. If you take the time at the outset to spell out the pieces of your application, as well as the behaviors those pieces need to exhibit, custom events can provide a powerful way for you to talk to those pieces, either one at a time or en masse. Once the behaviors of a piece have been described, it becomes trivial to trigger those behaviors from anywhere, allowing for rapid creation of and experimentation with interface options. Finally, custom events can enhance code readability and maintainability, by making clear the relationship between an element and its behaviors. You can see the full application at d m s c s o - v n s h m eo/utmeet.tl and d m s j / u t m e e t . sin the sample code. eo/scso-vnsj

jqfundamentals.com/book/index.html#chapter-1

111/111

S-ar putea să vă placă și