Você está na página 1de 105

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 Alie !"0
#nited States license" $ou are %ree to copy& distribute& transmit& and remi' this (or&
provided you attribute the (or to Rebecca Murphey as the original author and
re%erence the )it*ub repository %or the (or" +% you alter& trans%orm& or build upon this
(or& you may distribute the resulting (or only under the same& similar or a compatible
license" Any o% the above conditions can be (aived i% you get permission %rom the copyright
holder" ,or any reuse or distribution& you must mae clear to others the license terms o%
this (or" -he best (ay to do this is (ith a lin to the license"
Reporting Issues
$our %eedbac is essential to improving ./uery ,undamentals0 i% you see an error or an
opportunity %or improvement& please open an issue"
Suggesting Changes to Content
+% you1d lie to suggest a change to the boo& the strong pre%erence is that you submit a pull
re2uest rather than describing your proposed change in an issue" 3nce a pull re2uest is
submitted& it (ill be revie(ed %or inclusion"
Suggesting Additions to Content
+% you1ve come across a blog post or other resource that (ould be great %or inclusion in
./uery ,undamentals& please open an issue (ith a lin to the resource& and indicate in the
issue (hether you1ve already discussed inclusion o% the resource (ith the author"
Contributing Content
Contributions to ./uery ,undamentals are al(ays (elcome" -he best (ay to submit your
content %or consideration is to submit a pull re2uest to the ./uery learning repo"
Contents
Chapter 14 5elcome
Chapter 24 6avaScript 7asics
Chapter !4 ./uery 7asics
Chapter 84 ./uery Core
Chapter 94 :vents
Chapter ;4 :%%ects
Chapter <4 A.a'
Chapter =4 >lugins
Chapter ?4 >er%ormance 7est >ractices
Chapter 104 Code 3rgani@ation
Chapter 114 Custom :vents
List o% :'amples
:'ample 1"14 An e'ample o% inline 6avaScript
:'ample 1"24 An e'ample o% including e'ternal 6avaScript
:'ample 1"!4 :'ample o% an e'ample
:'ample 2"14 A simple variable declaration
:'ample 2"24 5hitespace has no meaning outside o% 2uotation mars
:'ample 2"!4 >arentheses indicate precedence
:'ample 2"84 -abs enhance readability& but have no special meaning
:'ample 2"94 Concatenation
:'ample 2";4 Multiplication and division
:'ample 2"<4 +ncrementing and decrementing
:'ample 2"=4 Addition vs" concatenation
:'ample 2"?4 ,orcing a string to act as a number
:'ample 2"104 ,orcing a string to act as a number Ausing the unary-plus operatorB
:'ample 2"114 Logical ACD and 3R operators
:'ample 2"124 Comparison operators
:'ample 2"1!4 ,lo( control
:'ample 2"184 Ealues that evaluate to true
:'ample 2"194 Ealues that evaluate to %alse
:'ample 2"1;4 -he ternary operator
:'ample 2"1<4 A s(itch statement
:'ample 2"1=4 Loops
:'ample 2"1?4 A typical %or loop
:'ample 2"204 A typical (hile loop
:'ample 2"214 A (hile loop (ith a combined conditional and incrementer
:'ample 2"224 A do-(hile loop
:'ample 2"2!4 Stopping a loop
:'ample 2"284 Sipping to the ne't iteration o% a loop
:'ample 2"294 A simple array
:'ample 2"2;4 Accessing array items by inde'
:'ample 2"2<4 -esting the si@e o% an array
:'ample 2"2=4 Changing the value o% an array item
:'ample 2"2?4 Adding elements to an array
:'ample 2"!04 5oring (ith arrays
:'ample 2"!14 Creating an Fob.ect literalF
:'ample 2"!24 ,unction Declaration
:'ample 2"!!4 Camed ,unction :'pression
:'ample 2"!84 A simple %unction
:'ample 2"!94 A %unction that returns a value
:'ample 2"!;4 A %unction that returns another %unction
:'ample 2"!<4 A sel%-e'ecuting anonymous %unction
:'ample 2"!=4 >assing an anonymous %unction as an argument
:'ample 2"!?4 >assing a named %unction as an argument
:'ample 2"804 -esting the type o% various variables
:'ample 2"814 A %unction invoed using ,unction"call
:'ample 2"824 A %unction created using ,unction"bind
:'ample 2"8!4 A %unction being attached to an ob.ect at runtime
:'ample 2"884 ,unctions have access to variables de%ined in the same scope
:'ample 2"894 Code outside the scope in (hich a variable (as de%ined does not have
access to the variable
:'ample 2"8;4 Eariables (ith the same name can e'ist in di%%erent scopes (ith
di%%erent values
:'ample 2"8<4 ,unctions can FseeF changes in variable values a%ter the %unction is
de%ined
:'ample 2"8=4 Scope insanity
:'ample 2"8?4 *o( to loc in the value o% iG
:'ample 2"904 Locing in the value o% i (ith a closure
:'ample 2"914 #sing a closure to access inner and outer ob.ect instances
simultaneously
:'ample !"14 A HAdocumentB"readyAB bloc
:'ample !"24 Shorthand %or HAdocumentB"readyAB
:'ample !"!4 >assing a named %unction instead o% an anonymous %unction
:'ample !"84 Selecting elements by +D
:'ample !"94 Selecting elements by class name
:'ample !";4 Selecting elements by attribute
:'ample !"<4 Selecting elements by compound CSS selector
:'ample !"=4 >seudo-selectors
:'ample !"?4 -esting (hether a selection contains elements
:'ample !"104 Storing selections in a variable
:'ample !"114 Re%ining selections
:'ample !"124 #sing %orm-related pseduo-selectors
:'ample !"1!4 Chaining
:'ample !"184 ,ormatting chained code
:'ample !"194 Restoring your original selection using H"%n"end
:'ample !"1;4 -he H"%n"html method used as a setter
:'ample !"1<4 -he html method used as a getter
:'ample !"1=4 )etting CSS properties
:'ample !"1?4 Setting CSS properties
:'ample !"204 5oring (ith classes
:'ample !"214 7asic dimensions methods
:'ample !"224 Setting attributes
:'ample !"2!4 )etting attributes
:'ample !"284 Moving around the D3M using traversal methods
:'ample !"294 +terating over a selection
:'ample !"2;4 Changing the *-ML o% an element
:'ample !"2<4 Moving elements using di%%erent approaches
:'ample !"2=4 Maing a copy o% an element
:'ample !"2?4 Creating ne( elements
:'ample !"!04 Creating a ne( element (ith an attribute ob.ect
:'ample !"!14 )etting a ne( element on to the page
:'ample !"!24 Creating and adding an element to the page at the same time
:'ample !"!!4 Manipulating a single attribute
:'ample !"!84 Manipulating multiple attributes
:'ample !"!94 #sing a %unction to determine an attributeIs ne( value
:'ample 8"14 Checing the type o% an arbitrary value
:'ample 8"24 Storing and retrieving data related to an element
:'ample 8"!4 Storing a relationship bet(een elements using H"%n"data
:'ample 8"84 >utting ./uery into no-con%lict mode
:'ample 8"94 #sing the H inside a sel%-e'ecuting anonymous %unction
:'ample 9"14 :vent binding using a convenience method
:'ample 9"24 :vent biding using the H"%n"bind method
:'ample 9"!4 :vent binding using the H"%n"bind method (ith data
:'ample 9"84 S(itching handlers using the H"%n"one method
:'ample 9"94 #nbinding all clic handlers on a selection
:'ample 9";4 #nbinding a particular clic handler
:'ample 9"<4 Camespacing events
:'ample 9"=4 7inding Multiple :vents
:'ample ;"14 A basic use o% a built-in e%%ect
:'ample ;"24 Setting the duration o% an e%%ect
:'ample ;"!4 Augmenting ./uery"%'"speeds (ith custom speed de%initions
:'ample ;"84 Running code (hen an animation is complete
:'ample ;"94 Run a callbac even i% there (ere no elements to animate
:'ample ;";4 Custom e%%ects (ith H"%n"animate
:'ample ;"<4 >er-property easing
:'ample <"14 #sing the core H"a.a' method
:'ample <"24 #sing ./ueryIs A.a' convenience methods
:'ample <"!4 #sing H"%n"load to populate an element
:'ample <"84 #sing H"%n"load to populate an element based on a selector
:'ample <"94 -urning %orm data into a 2uery string
:'ample <";4 Creating an array o% ob.ects containing %orm data
:'ample <"<4 #sing $/L and 6S3C>
:'ample <"=4 Setting up a loading indicator using A.a' :vents
:'ample ="14 Creating a plugin to add and remove a class on hover
:'ample ="24 -he Mie Alsup ./uery >lugin Development >attern
:'ample ="!4 A simple& state%ul plugin using the ./uery #+ (idget %actory
:'ample ="84 >assing options to a (idget
:'ample ="94 Setting de%ault options %or a (idget
:'ample =";4 Creating (idget methods
:'ample ="<4 Calling methods on a plugin instance
:'ample ="=4 Responding (hen an option is set
:'ample ="?4 >roviding callbacs %or user e'tension
:'ample ="104 7inding to (idget events
:'ample ="114 Adding a destroy method to a (idget
:'ample 10"14 An ob.ect literal
:'ample 10"24 #sing an ob.ect literal %or a ./uery %eature
:'ample 10"!4 -he module pattern
:'ample 10"84 #sing the module pattern %or a ./uery %eature
:'ample 10"94 #sing Re2uire6S4 A simple e'ample
:'ample 10";4 A simple 6avaScript %ile (ith dependencies
:'ample 10"<4 De%ining a Re2uire6S module that has no dependencies
:'ample 10"=4 De%ining a Re2uire6S module (ith dependencies
:'ample 10"?4 De%ining a Re2uire6S module that returns a %unction
7ac to top
Welcome
./uery is %ast becoming a must-have sill %or %ront-end developers" -he purpose o% this
boo is to provide an overvie( o% the ./uery 6avaScript library0 (hen youIre done (ith the
boo& you should be able to complete basic tass using ./uery& and have a solid basis %rom
(hich to continue your learning" -his boo (as designed as material to be used in a
classroom setting& but you may %ind it use%ul %or individual study"
-his is a hands-on class" 5e (ill spend a bit o% time covering a concept& and then you1ll
have the chance to (or on an e'ercise related to the concept" Some o% the e'ercises may
seem trivial0 others may be do(nright daunting" +n either case& there is no grade0 the goal
is simply to get you com%ortable (oring your (ay through problems you1ll commonly be
called upon to solve using ./uery" :'ample solutions to all o% the e'ercises are included in
the sample code"
Getting the Code
-he code (e1ll be using in this boo is hosted in a repository on )ithub" $ou can do(nload
a "@ip or "tar %ile o% the code& then uncompress it to use it on your server" +% you1re git-
inclined& you1re (elcome to clone or %or the repository"
Software
$ouIll (ant to have the %ollo(ing tools to mae the most o% the class4
-he ,ire%o' bro(ser
-he ,irebug e'tension %or ,ire%o'
A plain te't editor
,or the A.a' portions4 A local server Asuch as MAM> or 5AM>B& or an ,-> or SS*
client to access a remote server"
Adding JavaScript to Your Page
6avaScript can be included inline or by including an e'ternal %ile via a script tag" -he order
in (hich you include 6avaScript is important4 dependencies must be included be%ore the
script that depends on them"
,or the sae o% page per%ormance& 6avaScript should be included as close to the end o% your
*-ML as is practical" Multiple 6avaScript %iles should be combined %or production use"
Example 1.1: An example of inline JavaScript
1 <script>
2 console.log('hello');
3
</script>
:'ample 1"24 An e'ample o% including e'ternal 6avaScript
1
<script src='/js/jquery.js'></script>
6avaScript Debugging
A debugging tool is essential %or 6avaScript development" ,ire%o' provides a debugger via
the ,irebug e'tension0 Sa%ari and Chrome provide built-in consoles"
:ach console o%%ers4
single- and multi-line editors %or e'perimenting (ith 6avaScript
an inspector %or looing at the generated source o% your page
a Cet(or or Resources vie(& to e'amine net(or re2uests
5hen you are (riting 6avaScript code& you can use the %ollo(ing methods to send
messages to the console4
console"logAB %or sending general log messages
console"dirAB %or logging a bro(seable ob.ect
console"(arnAB %or logging (arnings
console"errorAB %or logging error messages
3ther console methods are also available& though they may di%%er %rom one bro(ser to
another" -he consoles also provide the ability to set brea points and (atch e'pressions in
your code %or debugging purposes"
Exercises
Most chapters in the boo conclude (ith one or more e'ercises" ,or some e'ercises& you1ll
be able to (or directly in ,irebug0 %or others& you (ill need to include other scripts a%ter
the ./uery script tag as directed in the individual e'ercises"
+n some cases& you (ill need to consult the ./uery documentation in order to complete an
e'ercise& as (e (on1t have covered all o% the relevant in%ormation in the boo" -his is by
design0 the ./uery library is large& and learning to %ind ans(ers in the documentation is an
important part o% the process"
*ere are a %e( suggestions %or tacling these problems4
,irst& mae sure you thoroughly understand the problem youIre being ased to
solve"
Ce't& %igure out (hich elements youIll need to access in order to solve the problem&
and determine ho( youIll get those elements" #se ,irebug to veri%y that youIre
getting the elements youIre a%ter"
,inally& %igure out (hat you need to do (ith the elements to solve the problem" +t
can be help%ul to (rite comments e'plaining (hat youIre going to do be%ore you try
to (rite the code to do it"
Do not be a%raid to mae mistaesJ Do not try to mae your code per%ect on the %irst tryJ
Maing mistaes and e'perimenting (ith solutions is part o% learning the library& and
you1ll be a better developer %or it" :'amples o% solutions %or these e'ercises are located in
the Ksolutions directory in the sample code"
Conventions used in this book
Methods that can be called on ./uery ob.ects (ill be re%erred to as H"%n"methodCame"
Methods that e'ist in the ./uery namespace but that cannot be called on ./uery ob.ects
(ill be re%erred to as H"methodCame" +% this doesnIt mean much to you& donIt (orry L it
should become clearer as you progress through the boo"
Example 1.3: Example of an example
1
// code ex!ples "ill pper li#e this
Remarks will appear like this.
Note
Cotes about a topic (ill appear lie this"
Reference Material
-here are any number o% articles and blog posts out there that address some aspect o%
./uery" Some are phenomenal0 some are do(nright (rong" 5hen you read an article about
./uery& be sure itIs taling about the same version as youIre using& and resist the urge to
.ust copy and paste L tae the time to understand the code in the article"
*ere are some e'cellent resources to use during your ./uery learning" -he most important
o% all is the ./uery source itsel%4 it contains& in code %orm& complete documentation o% the
library" +t is not a blac bo' L your understanding o% the library (ill gro( e'ponentially i%
you spend some time visiting it no( and again L and + highly recommend boomaring it
in your bro(ser and re%erring to it o%ten"
-he ./uery source
./uery documentation
./uery %orum
Delicious boomars
M.2uery +RC channel on ,reenode
>art +" 6avaScript 101
Back to top
JavaScript Basics
Overview
./uery is built on top o% 6avaScript& a rich and e'pressive language in its o(n right" -his
section covers the basic concepts o% 6avaScript& as (ell as some %re2uent pit%alls %or people
(ho have not used 6avaScript be%ore" 5hile it (ill be o% particular value to people (ith no
programming e'perience& even people (ho have used other programming languages may
bene%it %rom learning about some o% the peculiarities o% 6avaScript"
+% you1re interested in learning more about the 6avaScript language& + highly
recommend 6avaScript4 -he )ood >arts by Douglas Croc%ord"
Syntax Basics
#nderstanding statements& variable naming& (hitespace& and other basic 6avaScript
synta'"
Example 2.1: A simple variable declaration
1
$r %oo = 'hello "orld';
:'ample 2"24 5hitespace has no meaning outside o% 2uotation mars
1
$r %oo = 'hello "orld';
:'ample 2"!4 >arentheses indicate precedence
1 2 & 3 ' (; // returns 11; !ultipliction hppens %irst
2
2 & (3 ' (); // returns 1); ddition hppens %irst
:'ample 2"84 -abs enhance readability& but have no special meaning
1 $r %oo = %unction() *
2 console.log('hello');
3
+;
3perators
Basic Operators
7asic operators allo( you to manipulate values"
Example 2.5: Concatenation
1 $r %oo = 'hello';
2 $r ,r = '"orld';
3
-
console.log(%oo ' ' ' ' ,r); // 'hello "orld'
:'ample 2";4 Multiplication and division
1 2 & 3;
2
2 / 3;
:'ample 2"<4 +ncrementing and decrementing
1 $r i = 1;
2
3 $r j = ''i; // pre.incre!ent/ j equls 2; i equls 2
-
$r # = i''; // post.incre!ent/ # equls 2; i equls 3
3perations on Cumbers N Strings
+n 6avaScript& numbers and strings (ill occasionally behave in (ays you might not e'pect"
Example 2.8: Addition vs. concatenation
1 $r %oo = 1;
2 $r ,r = '2';
3
-
console.log(%oo ' ,r); // 12. uh oh
:'ample 2"?4 ,orcing a string to act as a number
1 $r %oo = 1;
2 $r ,r = '2';
3
- // coerce the string to nu!,er
(
console.log(%oo ' 0u!,er(,r));
-he Cumber constructor& (hen called as a %unction Alie aboveB (ill have the e%%ect o%
casting its argument into a number" $ou could also use the unary plus operator& (hich does
the same thing4
Example 2.10: Forcing a string to act as a number (using the unary-plus operator)
1
console.log(%oo ' ',r);
Logical 3perators
Logical operators allo( you to evaluate a series o% operands using ACD and 3R operations"
Example 2.11: Logical AND and OR operators
11 $r %oo = 1;
12 $r ,r = 1;
13 $r ,2 = 2;
1-
1( %oo 33 ,r; // returns 14 "hich is true
1) ,r 33 %oo; // returns 14 "hich is true
15
16 %oo 77 ,r; // returns 14 "hich is %lse
18 %oo 77 ,2; // returns 24 "hich is true
,2 77 %oo; // returns 14 "hich is true
-hough it may not be clear %rom the e'ample& the OO operator returns the value o% the %irst
truthy operand& or& in cases (here neither operand is truthy& itIll return the last o% both
operands" -he NN operator returns the value o% the %irst %alse operand& or the value o% the
last operand i% both operands are truthy"
7e sure to consult the section called P-ruthy and ,alsy -hingsQ %or more details on (hich
values evaluate to true and (hich evaluate to %alse"
Note
$ouIll sometimes see developers use these logical operators %or %lo( control instead o%
using i% statements" ,or e'ample4
1 // do so!ething "ith %oo i% %oo is truthy
2 %oo 77 do9o!ething(%oo);
3
- // set ,r to ,2 i% ,2 is truthy;
( // other"ise4 set it to the return
) // $lue o% crete:r()
5 $r ,r = ,2 33 crete:r();
-his style is 2uite elegant and pleasantly terse0 that said& it can be really hard to read&
especially %or beginners" + bring it up here so youIll recogni@e it in code you read& but + donIt
recommend using it until youIre e'tremely com%ortable (ith (hat it means and ho( you
can e'pect it to behave"
Comparison Operators
Comparison operators allo( you to test (hether values are e2uivalent or (hether values
are identical"
Example 2.12: Comparison operators
11 $r %oo = 1;
12 $r ,r = 1;
13 $r ,2 = '1';
1- $r ,i! = 2;
1(
1) %oo == ,r; // returns %lse
15 %oo ;= ,r; // returns true
16 %oo == ,2; // returns true; cre%ul;
18
11 %oo === ,2; // returns %lse
11 %oo ;== ,2; // returns true
12 %oo === prse<nt(,2); // returns true
13
1- %oo > ,i!; // returns %lse
1( ,i! > ,2; // returns true
1)
%oo <= ,2; // returns true
Conditional Code
Sometimes you only (ant to run a bloc o% code under certain conditions" ,lo( control L
via i% and else blocs L lets you run code only under certain conditions"
Example 2.13: Flow control
11 $r %oo = true;
12 $r ,r = %lse;
13
1- i% (,r) *
1( // this code "ill ne$er run
1) console.log('hello;');
15 +
16
18 i% (,r) *
11 // this code "on't run
11 + else *
12 i% (%oo) *
13 // this code "ill run
1- + else *
1( // this code "ould run i% %oo nd ,r "ere ,oth %lse
1) +
15
+
Cote
5hile curly braces arenIt strictly re2uired around single-line i% statements& using them
consistently& even (hen they arenIt strictly re2uired& maes %or vastly more readable code"
7e mind%ul not to de%ine %unctions (ith the same name multiple times (ithin
separate i%Kelse blocs& as doing so may not have the e'pected result"
Truthy and Falsy Things
+n order to use %lo( control success%ully& itIs important to understand (hich inds o% values
are FtruthyF and (hich inds o% values are F%alsy"F Sometimes& values that seem lie they
should evaluate one (ay actually evaluate another"
Example 2.14: Values that evaluate to true
1 '1';
2 'ny string';
3 =>; // n e!pty rry
- *+; // n e!pty o,ject
(
1; // ny non.2ero nu!,er
:'ample 2"194 Ealues that evaluate to %alse
1 1;
2 ''; // n e!pty string
3 00; // ?$9cript's @not..nu!,er@ $ri,le
- null;
(
unde%ined; // ,e cre%ul .. unde%ined cn ,e rede%ined;
Conditional Eariable Assignment (ith -he -ernary 3perator
Sometimes you (ant to set a variable to a value depending on some condition" $ou could
use an i%Kelse statement& but in many cases the ternary operator is more
convenient" RDe%inition4 -he ternary operator tests a condition0 i% the condition is true& it
returns a certain value& other(ise it returns a di%%erent value"S
Example 2.16: The ternary operator
1 // set %oo to 1 i% ,r is true;
2 // other"ise4 set %oo to 1
3
$r %oo = ,r A 1 / 1;
5hile the ternary operator can be used (ithout assigning the return value to a variable&
this is generally discouraged"
Switch Statements
Rather than using a series o% i%Kelse i%Kelse blocs& sometimes it can be use%ul to use a
s(itch statement instead" RDe%inition4 S(itch statements loo at the value o% a variable or
e'pression& and run di%%erent blocs o% code depending on the value"S
Example 2.17: A switch statement
11 s"itch (%oo) *
12
13 cse ',r'/
1- lert('the $lue "s ,r .. yy;');
1( ,re#;
1)
15 cse ',2'/
16 lert(',oo ,2 /(');
18 ,re#;
11
11 de%ult/
12 lert('e$erything else is just o#');
13 ,re#;
1-
1(
+
S(itch statements have some(hat %allen out o% %avor in 6avaScript& because o%ten the same
behavior can be accomplished by creating an ob.ect that has more potential %or reuse&
testing& etc" ,or e'ample4
11 $r stu%%BoCo = *
12 ',r' / %unction() *
13 lert('the $lue "s ,r .. yy;');
1- +4
1(
1) ',2' / %unction() *
15 lert(',oo ,2 /(');
16 +4
18
11 'de%ult' / %unction() *
11 lert('e$erything else is just o#');
12 +
13 +;
1-
1( i% (stu%%BoCo=%oo>) *
1) stu%%BoCo=%oo>();
15 + else *
16 stu%%BoCo='de%ult'>();
18 +
5eIll loo at ob.ects in greater depth later in this chapter"
Loops
Loops let you run a bloc o% code a certain number o% times"
Example 2.18: Loops
1 // logs 'try 1'4 'try 1'4 ...4 'try -'
2 %or ($r i=1; i<(; i'') *
3 console.log('try ' ' i);
-
+
Cote that in Loops even though (e use the ey(ord var be%ore the variable name i& this
does not FscopeF the variable i to the loop bloc" 5eIll discuss scope in depth later in this
chapter"
The for loop
A %or loop is made up o% %our statements and has the %ollo(ing structure4
1 %or (=initilistion>; =conditionl>; =itertion>)
2 =loop:ody>
-he initialisation statement is e'ecuted only once& be%ore the loop starts" +t gives you an
opportunity to prepare or declare any variables"
-he conditional statement is e'ecuted be%ore each iteration& and its return value decides
(hether or not the loop is to continue" +% the conditional statement evaluates to a %alsey
value then the loop stops"
-he iteration statement is e'ecuted at the end o% each iteration and gives you an
opportunity to change the state o% important variables" -ypically& this (ill involve
incrementing or decrementing a counter and thus bringing the loop ever closer to its end"
-he loop7ody statement is (hat runs on every iteration" +t can contain anything you (ant"
$ouIll typically have multiple statements that need to be e'ecuted and so (ill (rap them in
a bloc A T"""UB"
*ereIs a typical %or loop4
Example 2.19: A typical for loop
1 %or ($r i = 14 li!it = 111; i < li!it; i'') *
2 // Bhis ,loc# "ill ,e executed 111 ti!es
3 console.log('Durrently t ' ' i);
- // 0ote/ the lst log "ill ,e @Durrently t 88@
(
+
-he (hile loop
A (hile loop is similar to an i% statement& e'cept that its body (ill eep e'ecuting until the
condition evaluates to %alse"
1 "hile (=conditionl>) =loop:ody>
*ereIs a typical (hile loop4
Example 2.20: A typical while loop
1 $r i = 1;
2 "hile (i < 111) *
3
- // Bhis ,loc# "ill ,e executed 111 ti!es
( console.log('Durrently t ' ' i);
)
5 i''; // incre!ent i
6
8
+
$ouIll notice that (eIre having to increment the counter (ithin the loopIs body" +t is
possible to combine the conditional and incrementer& lie so4
Example 2.21: A while loop with a combined conditional and incrementer
1 $r i = .1;
2 "hile (''i < 111) *
3 // Bhis ,loc# "ill ,e executed 111 ti!es
- console.log('Durrently t ' ' i);
(
+
Cotice that (eIre starting at -1 and using the pre%i' incrementer AVViB"
The do-while loop
-his is almost e'actly the same as the (hile loop& e'cept %or the %act that the loopIs body is
e'ecuted at least once be%ore the condition is tested"
1 do =loop:ody> "hile (=conditionl>)
*ereIs a do-(hile loop4
Example 2.22: A do-while loop
1 do *
2
3 // E$en though the condition e$lutes to %lse
- // this loop's ,ody "ill still execute once.
(
) lert('Fi there;');
5
6
+ "hile (%lse);
-hese types o% loops are 2uite rare since only %e( situations re2uire a loop that blindly
e'ecutes at least once" Regardless& itIs good to be a(are o% it"
Breaking and continuing
#sually& a loopIs termination (ill result %rom the conditional statement not evaluating to
true& but it is possible to stop a loop in its tracs %rom (ithin the loopIs body (ith
the brea statement"
Example 2.23: Stopping a loop
1 %or ($r i = 1; i < 11; i'') *
2 i% (so!ething) *
3 ,re#;
- +
(
+
$ou may also (ant to continue the loop (ithout e'ecuting more o% the loopIs body" -his is
done using the continue statement"
Example 2.24: Skipping to the next iteration of a loop
11 %or ($r i = 1; i < 11; i'') *
12
13 i% (so!ething) *
1- continue;
1( +
1)
15 // Bhe %ollo"ing stte!ent "ill only ,e executed
16 // i% the conditionl 'so!ething' hs not ,een !et
18 console.log('< h$e ,een reched');
11
11
+
Reserved 5ords
6avaScript has a number o% Preserved (ords&Q or (ords that have special meaning in the
language" $ou should avoid using these (ords in your code e'cept (hen using them (ith
their intended meaning"
abstract
boolean
brea
byte
case
catch
char
class
const
continue
debugger
de%ault
delete
do
double
else
enum
e'port
e'tends
%inal
%inally
%loat
%or
%unction
goto
i%
implements
import
in
instanceo%
int
inter%ace
long
native
ne(
pacage
private
protected
public
return
short
static
super
s(itch
synchroni@ed
this
thro(
thro(s
transient
try
typeo%
var
void
volatile
(hile
(ith
Arrays
Arrays are @ero-inde'ed lists o% values" -hey are a handy (ay to store a set o% related items
o% the same type Asuch as stringsB& though in reality& an array can include multiple types o%
items& including other arrays"
Example 2.25: A simple array
1
$r !yGrry = = 'hello'4 '"orld' >;
:'ample 2"2;4 Accessing array items by inde'
1 $r !yGrry = = 'hello'4 '"orld'4 '%oo'4 ',r' >;
2
console.log(!yGrry=3>); // logs ',r'
:'ample 2"2<4 -esting the si@e o% an array
1 $r !yGrry = = 'hello'4 '"orld' >;
2
console.log(!yGrry.length); // logs 2
:'ample 2"2=4 Changing the value o% an array item
1 $r !yGrry = = 'hello'4 '"orld' >;
2
!yGrry=1> = 'chnged';
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 $r !yGrry = = 'hello'4 '"orld' >;
2
!yGrry.push('ne"');
:'ample 2"!04 5oring (ith arrays
1 $r !yGrry = = 'h'4 'e'4 'l'4 'l'4 'o' >;
2 $r !y9tring = !yGrry.join(''); // 'hello'
3
$r !y9plit = !y9tring.split(''); // = 'h'4 'e'4 'l'4 'l'4 'o' >
3b.ects
3b.ects contain one or more ey-value pairs" -he ey portion can be any string" -he value
portion can be any type o% value4 a number& a string& an array& a %unction& or even another
ob.ect"
RDe%inition4 5hen one o% these values is a %unction& it1s called a method o% the
ob.ect"S 3ther(ise& they are called properties"
As it turns out& nearly everything in 6avaScript is an ob.ect L arrays& %unctions& numbers&
even strings L and they all have properties and methods"
Example 2.31: Creating an "object literal"
11 $r !yH,ject = *
12 syFello / %unction() *
13 console.log('hello');
1- +4
1(
1) !y0!e / 'Ie,ecc'
15 +;
16
18 !yH,ject.syFello(); // logs 'hello'
11
console.log(!yH,ject.!y0!e); // logs 'Ie,ecc'
Cote
5hen creating ob.ect literals& you should note that the ey portion o% each ey-value pair
can be (ritten as any valid 6avaScript identi%ier& a string A(rapped in 2uotesB or a number4
1 $r !yH,ject = *
2 $lid<denti%ier/ 1234
3 'so!e string'/ -()4
- 88888/ 568
( +;
3b.ect literals can be e'tremely use%ul %or code organi@ation0 %or more in%ormation&
read #sing 3b.ects to 3rgani@e $our Code by Rebecca Murphey"
Functions
,unctions contain blocs o% code that need to be e'ecuted repeatedly" ,unctions can tae
@ero or more arguments& and can optionally return a value"
,unctions can be created in a variety o% (ays4
Example 2.32: Function Declaration
1
%unction %oo() * /& do so!ething &/ +
:'ample 2"!!4 Camed ,unction :'pression
1
$r %oo = %unction() * /& do so!ething &/ +
prefer the named function e!pression method of setting a function's name, for some
rather in"depth and technical reasons. #ou are likely to see both methods used in others'
$ava%cript code.
Using Functions
Example 2.34: A simple function
1 $r greet = %unction(person4 greeting) *
2 $r text = greeting ' '4 ' ' person;
3 console.log(text);
- +;
(
)
5
greet('Ie,ecc'4 'Fello');
:'ample 2"!94 A %unction that returns a value
1 $r greet = %unction(person4 greeting) *
2 $r text = greeting ' '4 ' ' person;
3 return text;
- +;
(
)
console.log(greet('Ie,ecc'4'hello'));
:'ample 2"!;4 A %unction that returns another %unction
1 $r greet = %unction(person4 greeting) *
2 $r text = greeting ' '4 ' ' person;
3 return %unction() * console.log(text); +;
- +;
(
)
5 $r greeting = greet('Ie,ecc'4 'Fello');
6 greeting();
Sel%-:'ecuting Anonymous ,unctions
A common pattern in 6avaScript is the sel%-e'ecuting anonymous %unction" -his pattern
creates a %unction e'pression and then immediately e'ecutes the %unction" -his pattern is
e'tremely use%ul %or cases (here you (ant to avoid polluting the global namespace (ith
your code L no variables declared inside o% the %unction are visible outside o% it"
Example 2.37: A self-executing anonymous function
1 (%unction()*
2 $r %oo = 'Fello "orld';
3 +)();
-
(
)
console.log(%oo); // unde%ined;
,unctions as Arguments
+n 6avaScript& %unctions are F%irst-class citi@ensF Nmdash they can be assigned to variables
or passed to other %unctions as arguments" >assing %unctions as arguments is an e'tremely
common idiom in ./uery"
Example 2.38: Passing an anonymous function as an argument
1 $r !yJn = %unction(%n) *
2 $r result = %n();
3 console.log(result);
- +;
(
)
!yJn(%unction() * return 'hello "orld'; +); // logs 'hello "orld'
:'ample 2"!?4 >assing a named %unction as an argument
11 $r !yJn = %unction(%n) *
12 $r result = %n();
13 console.log(result);
1- +;
1(
1) $r !yHtherJn = %unction() *
15 return 'hello "orld';
16 +;
18
11
!yJn(!yHtherJn); // logs 'hello "orld'
-esting -ype
6avaScript o%%ers a (ay to test the FtypeF o% a variable" *o(ever& the result can be con%using
L %or e'ample& the type o% an Array is Fob.ectF"
+tIs common practice to use the typeo% operator (hen trying to determining the type o% a
speci%ic value"
Example 2.40: Testing the type of various variables
11 $r !yJunction = %unction() *
12 console.log('hello');
13 +;
1-
1( $r !yH,ject = *
1) %oo / ',r'
15 +;
16
18 $r !yGrry = = ''4 ','4 'c' >;
11
11 $r !y9tring = 'hello';
12
13 $r !y0u!,er = 3;
1-
1( typeo% !yJunction; // returns '%unction'
1) typeo% !yH,ject; // returns 'o,ject'
15 typeo% !yGrry; // returns 'o,ject' .. cre%ul;
16 typeo% !y9tring; // returns 'string';
18 typeo% !y0u!,er; // returns 'nu!,er'
21
21 typeo% null; // returns 'o,ject' .. cre%ul;
22
23
2- i% (!yGrry.push 77 !yGrry.slice 77 !yGrry.join) *
2( // pro,,ly n rry
2) // (this is clled @duc# typing@)
25 +
26
28 i% (H,ject.prototype.to9tring.cll(!yGrry) === '=o,ject Grry>') *
31 // Ce%initely n rry;
31 // Bhis is "idely considered s the !ost ro,ust "y
32 // to deter!ine i% speci%ic $lue is n Grry.
33
+
./uery o%%ers utility methods to help you determine the type o% an arbitrary value" -hese
(ill be covered later"
The this keyword
+n 6avaScript& as in most ob.ect-oriented programming languages& this is a special ey(ord
that is used (ithin methods to re%er to the ob.ect on (hich a method is being invoed" -he
value o% this is determined using a simple series o% steps4
1. +% the %unction is invoed using ,unction"call or ,unction"apply& this (ill be set to
the %irst argument passed to callKapply" +% the %irst argument passed to callKapply
is null or unde%ined& this (ill re%er to the global ob.ect A(hich is the (indo( ob.ect
in 5eb bro(sersB"
2. +% the %unction being invoed (as created using ,unction"bind& this (ill be the %irst
argument that (as passed to bind at the time the %unction (as created"
3. +% the %unction is being invoed as a method o% an ob.ect& this (ill re%er to that
ob.ect"
4. 3ther(ise& the %unction is being invoed as a standalone %unction not attached to
any ob.ect& and this (ill re%er to the global ob.ect"
Example 2.41: A function invoked using Function.call
11 $r !yH,ject = *
12 syFello / %unction() *
13 console.log('Fi; Ky n!e is ' ' this.!y0!e);
1- +4
1(
1) !y0!e / 'Ie,ecc'
15 +;
16
18 $r secondH,ject = *
11 !y0!e / 'Dolin'
11 +;
12
13
!yH,ject.syFello(); // logs 'Fi; Ky n!e is
Ie,ecc'
1-
!yH,ject.syFello.cll(secondH,ject); // logs 'Fi; Ky n!e is Dolin'
:'ample 2"824 A %unction created using ,unction"bind
11 $r !y0!e = 'the glo,l o,ject'4
12
13 syFello = %unction () *
1- console.log('Fi; Ky n!e is ' ' this.!y0!e);
1( +4
1)
15 !yH,ject = *
16 !y0!e / 'Ie,ecc'
18 +;
11
11 $r !yH,jectFello = syFello.,ind(!yH,ject);
12
13 syFello(); // logs 'Fi; Ky n!e is the glo,l o,ject'
1-
!yH,jectFello(); // logs 'Fi; Ky n!e is Ie,ecc'
:'ample 2"8!4 A %unction being attached to an ob.ect at runtime
11 $r !y0!e = 'the glo,l o,ject'4
12
13 syFello = %unction() *
1- console.log('Fi; Ky n!e is ' ' this.!y0!e);
1( +4
1)
15 !yH,ject = *
16 !y0!e / 'Ie,ecc'
18 +4
11
11 secondH,ject = *
12 !y0!e / 'Dolin'
13 +;
1-
1( !yH,ject.syFello = syFello;
1) secondH,ject.syFello = syFello;
15
16 syFello(); // logs 'Fi; Ky n!e is the glo,l o,ject'
18 !yH,ject.syFello(); // logs 'Fi; Ky n!e is Ie,ecc'
21
secondH,ject.syFello(); // logs 'Fi; Ky n!e is Dolin'
Cote
5hen invoing a %unction deep (ithin a long namespace& it is o%ten tempting to reduce the
amount o% code you need to type by storing a re%erence to the actual %unction as a single&
shorter variable" +t is important not to do this (ith instance methods as this (ill cause the
value o% this (ithin the %unction to change& leading to incorrect code operation" ,or
instance4
11 $r !y0!espce = *
12 !yH,ject / *
13 syFello / %unction() *
1- console.log('Fi; Ky n!e is ' ' this.!y0!e);
1( +4
1)
15 !y0!e / 'Ie,ecc'
16 +
18 +;
11
11 $r hello = !y0!espce.!yH,ject.syFello;
12
13 hello(); // logs 'Fi; Ky n!e is unde%ined'
$ou can& ho(ever& sa%ely reduce everything up to the ob.ect on (hich the method is
invoed4
11 $r !y0!espce = *
12 !yH,ject / *
13 syFello / %unction() *
1- console.log('Fi; Ky n!e is ' ' this.!y0!e);
1( +4
1)
15 !y0!e / 'Ie,ecc'
16 +
18 +;
11
11 $r o,j = !y0!espce.!yH,ject;
12
13 o,j.syFello(); // logs 'Fi; Ky n!e is Ie,ecc'
Scope
FScopeF re%ers to the variables that are available to a piece o% code at a given time" A lac o%
understanding o% scope can lead to %rustrating debugging e'periences"
5hen a variable is declared inside o% a %unction using the var ey(ord& it is only available
to code inside o% that %unction L code outside o% that %unction cannot access the variable"
3n the other hand& %unctions de%ined inside that %unction (ill have access to to the
declared variable"
,urthermore& variables that are declared inside a %unction (ithout the var ey(ord are not
local to the %unction L 6avaScript (ill traverse the scope chain all the (ay up to the
(indo( scope to %ind (here the variable (as previously de%ined" +% the variable (asnIt
previously de%ined& it (ill be de%ined in the global scope& (hich can have e'tremely
une'pected conse2uences0
Example 2.44: Functions have access to variables defined in the same scope
1 $r %oo = 'hello';
2
3 $r syFello = %unction() *
- console.log(%oo);
( +;
)
5 syFello(); // logs 'hello'
6
console.log(%oo); // lso logs 'hello'
:'ample 2"894 Code outside the scope in (hich a variable (as de%ined does not have access to the
variable
1 $r syFello = %unction() *
2 $r %oo = 'hello';
3 console.log(%oo);
- +;
(
) syFello(); // logs 'hello'
5
console.log(%oo); // doesn't log nything
:'ample 2"8;4 Eariables (ith the same name can e'ist in di%%erent scopes (ith di%%erent values
1 $r %oo = '"orld';
2
3 $r syFello = %unction() *
- $r %oo = 'hello';
( console.log(%oo);
) +;
5
6 syFello(); // logs 'hello'
8
console.log(%oo); // logs '"orld'
:'ample 2"8<4 ,unctions can FseeF changes in variable values a%ter the %unction is de%ined
11 $r !yJunction = %unction() *
12 $r %oo = 'hello';
13
1- $r !yJn = %unction() *
1( console.log(%oo);
1) +;
15
16 %oo = '"orld';
18
11 return !yJn;
11 +;
12
13 $r % = !yJunction();
1-
%(); // logs '"orld' .. uh oh
:'ample 2"8=4 Scope insanity
11 // sel%.executing nony!ous %unction
12 (%unction() *
13 $r ,2 = 1;
1- $r ,i! = %unction() * lert(,2); +;
1( ,r = %unction() * lert(,2); +;
1) +)();
15
16 console.log(,2); // ,2 is not de%ined outside o% the %unction
18
11 ,r(); // ,r is de%ined outside o% the nony!ous %unction
11 // ,ecuse it "sn't declred "ith $r; %urther!ore4
12 // ,ecuse it "s de%ined in the s!e scope s ,24
13 // it hs ccess to ,2 e$en though other code
1- // outside o% the %unction does not
1(
1) ,i!(); // ,i! is not de%ined outside o% the nony!ous %unction4
15
// so this "ill result in n error
Closures
Closures are an e'tension o% the concept o% scope L %unctions have access to variables that
(ere available in the scope (here the %unction (as created" +% that1s con%using& don1t (orry4
closures are generally best understood by e'ample"
+n P,unctions can FseeF changes in variable values a%ter the %unction is de%inedQ& (e sa(
ho( %unctions have access to changing variable values" -he same sort o% behavior e'ists
(ith %unctions de%ined (ithin loops L the %unction FseesF the change in the variableIs value
even a%ter the %unction is de%ined& resulting in all clics alerting 9"
Example 2.49: How to lock in the value of i?
1 /& this "on't ,eh$e s "e "nt it to; &/
2 /& e$ery clic# "ill lert ( &/
3 %or ($r i=1; i<(; i'') *
- L('<p>clic# !e</p>').ppendBo(',ody').clic#(%unction() *
( lert(i);
) +);
5
+
:'ample 2"904 Locing in the value o% i (ith a closure
1
/& %ix/ McloseN the $lue o% i inside creteJunction4 so it "on't
chnge &/
2 $r creteJunction = %unction(i) *
3 return %unction() * lert(i); +;
- +;
(
) %or ($r i=1; i<(; i'') *
5 L('<p>clic# !e</p>').ppendBo(',ody').clic#(creteJunction(i));
6
+
Closures can also be used to resolve issues (ith the this ey(ord& (hich is uni2ue to each
scope4
Example 2.51: Using a closure to access inner and outer object instances simultaneously
11 $r outerH,j = *
12 !y0!e / 'outer'4
13 outerJunction / %unction () *
1-
1(
// pro$ide re%erence to outerH,j through innerJunction's
closure
1) $r sel% = this;
15
16 $r innerH,j = *
18 !y0!e / 'inner'4
11 innerJunction / %unction () *
11
console.log(sel%.!y0!e4 this.!y0!e); // logs
'outer inner'
12 +
13 +;
1-
1( innerH,j.innerJunction();
1)
15 console.log(this.!y0!e); // logs 'outer'
16 +
18 +;
21
21
outerH,j.outerJunction();
-his mechanism can be particularly use%ul (hen dealing (ith callbacs& though in those
cases& it is o%ten better to use ,unction"bind& (hich (ill avoid any overhead associated (ith
scope traversal"
>art ++" ./uery4 7asic Concepts
Back to top
jQuery Basics
$(document).ready()
$ou cannot sa%ely manipulate a page until the document is Pready"Q ./uery detects this
state o% readiness %or you0 code included inside HAdocumentB"readyAB (ill only run once the
page is ready %or 6avaScript code to e'ecute"
Example 3.1: A $(document).ready() block
1 L(docu!ent).redy(%unction() *
2 console.log('redy;');
3
+);
-here is a shorthand %or HAdocumentB"readyAB that you (ill sometimes see0 ho(ever& +
recommend against using it i% you are (riting code that people (ho arenIt e'perienced (ith
./uery may see"
Example 3.2: Shorthand for $(document).ready()
1 L(%unction() *
2 console.log('redy;');
3
+);
$ou can also pass a named %unction to HAdocumentB"readyAB instead o% passing an
anonymous %unction"
Example 3.3: Passing a named function instead of an anonymous function
1 %unction redyJn() *
2 // code to run "hen the docu!ent is redy
3 +
-
(
)
L(docu!ent).redy(redyJn);
Selecting :lements
-he most basic concept o% ./uery is to Pselect some elements and do something (ith
them"Q ./uery supports most CSS! selectors& as (ell as some non-standard selectors" ,or a
complete selector re%erence& visit http4KKapi".2uery"comKcategoryKselectorsK"
,ollo(ing are a %e( e'amples o% common selection techni2ues"
Example 3.4: Selecting elements by ID
1
L('O!y<d'); // note <Cs !ust ,e unique per pge
:'ample !"94 Selecting elements by class name
1
L('di$.!yDlss'); // per%or!nce i!pro$es i% you speci%y ele!ent type
:'ample !";4 Selecting elements by attribute
1
L('input=n!e=%irstPn!e>'); // ,e"re4 this cn ,e $ery slo"
:'ample !"<4 Selecting elements by compound CSS selector
1
L('Ocontents ul.people li');
:'ample !"=4 >seudo-selectors
1 L('.externl/%irst');
2 L('tr/odd');
3 L('O!yJor! /input'); // select ll input.li#e ele!ents in %or!
- L('di$/$isi,le');
( L('di$/gt(2)'); // ll except the %irst three di$s
)
L('di$/ni!ted'); // ll currently ni!ted di$s
Cote
5hen you use the 4visible and 4hidden pseudo-selectors& ./uery tests the actual visibility o%
the element& not its CSS visibility or display L that is& it loos to see i% the
elementIs physical height and (idth on the page are both greater than @ero" *o(ever& this
test doesnIt (or (ith WtrX elements0 in this case& ./uery does chec the
CSS display property& and considers an element hidden i% its display property is set
to none" :lements that have not been added to the D3M (ill al(ays be considered hidden&
even i% the CSS that (ould a%%ect them (ould render them visible" ASee the Manipulation
section later in this chapter to learn ho( to create and add elements to the D3M"B
,or re%erence& here is the code ./uery uses to determine (hether an element is visible or
hidden& (ith comments added %or clarity4
11 jQuery.expr.%ilters.hidden = %unction( ele! ) *
12 $r "idth = ele!.o%%setRidth4 height = ele!.o%%setFeight4
13 s#ip = ele!.node0!e.toSo"erDse() === @tr@;
1-
1( // does the ele!ent h$e 1 height4 1 "idth4
1) // nd it's not <tr>A
15 return "idth === 1 77 height === 1 77 ;s#ip A
16
18 // then it !ust ,e hidden
11 true /
11
12 // ,ut i% it hs "idth nd height
13 // nd it's not <tr>
1- "idth > 1 77 height > 1 77 ;s#ip A
1(
1) // then it !ust ,e $isi,le
15 %lse /
16
18 // i% "e get here4 the ele!ent hs "idth
21 // nd height4 ,ut it's lso <tr>4
21 // so chec# its disply property to
22 // decide "hether it's hidden
23 jQuery.curD99(ele!4 @disply@) === @none@;
2- +;
2(
2) jQuery.expr.%ilters.$isi,le = %unction( ele! ) *
25 return ;jQuery.expr.%ilters.hidden( ele! );
26 +;
Choosing Selectors
Choosing good selectors is one (ay to improve the per%ormance o% your 6avaScript" A little
speci%icity L %or e'ample& including an element type such as div (hen selecting elements
by class name L can go a long (ay" )enerally& any time you can give ./uery a hint about
(here it might e'pect to %ind (hat youIre looing %or& you should" 3n the other hand& too
much speci%icity can be a bad thing" A selector such as Mmy-able thead tr th"special is
overill i% a selector such as Mmy-able th"special (ill get you (hat you (ant"
./uery o%%ers many attribute-based selectors& allo(ing you to mae selections based on the
content o% arbitrary attributes using simpli%ied regular e'pressions"
1 // %ind ll <>s "hose rel ttri,ute
2 // ends "ith @thinger@
3 L(@=relL='thinger'>@);
5hile these can be use%ul in a pinch& they can also be e'tremely slo( L + once (rote an
attribute-based selector that loced up my page %or multiple seconds" 5herever possible&
mae your selections using +Ds& class names& and tag names"
5ant to no( moreG >aul +rish has a great presentation about improving per%ormance in
6avaScript& (ith several slides %ocused speci%ically on selector per%ormance"
Does My Selection Contain Any Elements?
3nce youIve made a selection& youIll o%ten (ant to no( (hether you have anything to
(or (ith" $ou may be inclined to try something lie4
1 i% (L('di$.%oo')) * ... +
-his (onIt (or" 5hen you mae a selection using HAB& an ob.ect is al(ays returned& and
ob.ects al(ays evaluate to true" :ven i% your selection doesnIt contain any elements& the
code inside the i% statement (ill still run"
+nstead& you need to test the selectionIs length property& (hich tells you ho( many
elements (ere selected" +% the ans(er is 0& the length property (ill evaluate to %alse (hen
used as a boolean value"
Example 3.9: Testing whether a selection contains elements
1
i% (L('di$.%oo').length) * ... +
Saving Selections
:very time you mae a selection& a lot o% code runs& and ./uery doesnIt do caching o%
selections %or you" +% youIve made a selection that you might need to mae again& you
should save the selection in a variable rather than maing the selection repeatedly"
Example 3.10: Storing selections in a variable
1
$r Ldi$s = L('di$');
Cote
+n PStoring selections in a variableQ& the variable name begins (ith a dollar sign" #nlie in
other languages& thereIs nothing special about the dollar sign in 6avaScript L itIs .ust
another character" 5e use it here to indicate that the variable contains a ./uery ob.ect"
-his practice L a sort o% *ungarian notation L is merely convention& and is not
mandatory"
3nce youIve stored your selection& you can call ./uery methods on the variable you stored
it in .ust lie you (ould have called them on the original selection"
Note
A selection only %etches the elements that are on the page (hen you mae the selection" +%
you add elements to the page later& youIll have to repeat the selection or other(ise add
them to the selection stored in the variable" Stored selections donIt magically update (hen
the D3M changes"
Refining & Filtering Selections
Sometimes you have a selection that contains more than (hat youIre a%ter0 in this case& you
may (ant to re%ine your selection" ./uery o%%ers several methods %or @eroing in on e'actly
(hat youIre a%ter"
Example 3.11: Refining selections
1 L('di$.%oo').hs('p'); // di$.%oo ele!ents tht contin <p>'s
2
L('h1').not('.,r'); // h1 ele!ents tht don't h$e clss
o% ,r
3
L('ul li').%ilter('.current'); // unordered list ite!s "ith clss o%
current
- L('ul li').%irst(); // just the %irst unordered list ite!
(
L('ul li').eq((); // the sixth
Selecting ,orm :lements
./uery o%%ers several pseudo-selectors that help you %ind elements in your %orms0 these are
especially help%ul because it can be di%%icult to distinguish bet(een %orm elements based on
their state or type using standard CSS selectors"
:button
Selects WbuttonX elements and elements (ith typeYFbuttonF
:checkbox
Selects inputs (ith typeYFchecbo'F
:checked
Selects checed inputs
:disabled
Selects disabled %orm elements
:enabled
Selects enabled %orm elements
:file
Selects inputs (ith typeYF%ileF
:image
Selects inputs (ith typeYFimageF
:input
Selects WinputX& Wte'tareaX& and WselectX elements
:password
Selects inputs (ith typeYFpass(ordF
:radio
Selects inputs (ith typeYFradioF
:reset
Selects inputs (ith typeYFresetF
:selected
Selects options that are selected
:submit
Selects inputs (ith typeYFsubmitF
:text
Selects inputs (ith typeYFte'tF
Example 3.12: Using form-related pseduo-selectors
1
L('O!yJor! /input'); // get ll ele!ents tht ccept input
5oring (ith Selections
3nce you have a selection& you can call methods on the selection" Methods generally come
in t(o di%%erent %lavors4 getters and setters" )etters return a property o% the %irst selected
element0 setters set a property on all selected elements"
Chaining
+% you call a method on a selection and that method returns a ./uery ob.ect& you can
continue to call ./uery methods on the ob.ect (ithout pausing %or a semicolon"
Example 3.13: Chaining
1
L('Ocontent').%ind('h3').eq(2).ht!l('ne" text %or the third h3;');
+% you are (riting a chain that includes several steps& you Aand the person (ho comes a%ter
youB may %ind your code more readable i% you brea the chain over several lines"
Example 3.14: Formatting chained code
1 L('Ocontent')
2 .%ind('h3')
3 .eq(2)
-
.ht!l('ne" text %or the third h3;');
+% you change your selection in the midst o% a chain& ./uery provides the H"%n"end method
to get you bac to your original selection"
Example 3.15: Restoring your original selection using $.fn.end
1 L('Ocontent')
2 .%ind('h3')
3 .eq(2)
- .ht!l('ne" text %or the third h3;')
( .end() // restores the selection to ll h3's in Ocontent
) .eq(1)
5
.ht!l('ne" text %or the %irst h3;');
Cote
Chaining is e'traordinarily po(er%ul& and itIs a %eature that many libraries have adapted
since it (as made popular by ./uery" *o(ever& it must be used (ith care" :'tensive
chaining can mae code e'tremely di%%icult to modi%y or debug" -here is no hard-and-%ast
rule to ho( long a chain should be L .ust no( that it is easy to get carried a(ay"
Getters & Setters
./uery PoverloadsQ its methods& so the method used to set a value generally has the same
name as the method used to get a value" 5hen a method is used to set a value& it is called a
setter" 5hen a method is used to get Aor readB a value& it is called a getter" Setters a%%ect all
elements in a selection0 getters get the re2uested value only %or the %irst element in the
selection"
Example 3.16: The $.fn.html method used as a setter
1
L('h1').ht!l('hello "orld');
:'ample !"1<4 -he html method used as a getter
1
L('h1').ht!l();
Setters return a ./uery ob.ect& allo(ing you to continue to call ./uery methods on your
selection0 getters return (hatever they (ere ased to get& meaning you cannot continue to
call ./uery methods on the value returned by the getter"
CSS, Styling, & Dimensions
./uery includes a handy (ay to get and set CSS properties o% elements"
Note
CSS properties that normally include a hyphen need to be camel cased in 6avaScript" ,or
e'ample& the CSS property %ont-si@e is e'pressed as %ontSi@e(hen used as a property name
in 6avaScript" -his does not apply& ho(ever& (hen passing the name o% a CSS property to
the H"%n"css method as a string L in that case& either the camel cased or hyphenated %orm
(ill (or"
Example 3.18: Getting CSS properties
1 L('h1').css('%ont9i2e'); // returns string such s @18px@
2
L('h1').css('%ont.si2e'); // lso "or#s
:'ample !"1?4 Setting CSS properties
1 L('h1').css('%ont9i2e'4 '111px'); // setting n indi$idul property
2
L('h1').css(* '%ont9i2e' / '111px'4 'color' / 'red' +); // setting
!ultiple properties
&ote the style of the argument we use on the second line ' it is an ob(ect that contains
multiple properties. )his is a common way to pass multiple arguments to a function, and
many (*uery setter methods accept ob(ects to set mulitple values at once.
Using CSS Classes for Styling
As a getter& the H"%n"css method is valuable0 ho(ever& it should generally be avoided as a
setter in production-ready code& because you donIt (ant presentational in%ormation in
your 6avaScript" +nstead& (rite CSS rules %or classes that describe the various visual states&
and then simply change the class on the element you (ant to a%%ect"
Example 3.20: Working with classes
1 $r Lh1 = L('h1');
2
3 Lh1.ddDlss(',ig');
- Lh1.re!o$eDlss(',ig');
( Lh1.toggleDlss(',ig');
)
5
i% (Lh1.hsDlss(',ig')) * ... +
Classes can also be use%ul %or storing state in%ormation about an element& such as
indicating that an element is selected"
Dimensions
./uery o%%ers a variety o% methods %or obtaining and modi%ying dimension and position
in%ormation about an element"
-he code in P7asic dimensions methodsQ& is .ust a very brie% overvie( o% the dimensions
%unctionality in ./uery0 %or complete details about ./uery dimension methods&
visit http4KKapi".2uery"comKcategoryKdimensionsK"
Example 3.21: Basic dimensions methods
1 L('h1')."idth('(1px'); // sets the "idth o% ll F1 ele!ents
2 L('h1')."idth(); // gets the "idth o% the %irst F1
3
- L('h1').height('(1px'); // sets the height o% ll F1 ele!ents
( L('h1').height(); // gets the height o% the %irst F1
)
5 L('h1').position(); // returns n o,ject contining position
6 // in%or!tion %or the %irst F1 relti$e to
8
// its @o%%set (positioned) prent@
Attributes
An elementIs attributes can contain use%ul in%ormation %or your application& so itIs
important to be able to get and set them"
-he H"%n"attr method acts as both a getter and a setter" As (ith
the H"%n"css method& H"%n"attr as a setter can accept either a ey and a value& or an ob.ect
containing one or more eyKvalue pairs"
Example 3.22: Setting attributes
1 L('').ttr('hre%'4 'llKyFre%sGreBhe9!e0o".ht!l');
2 L('').ttr(*
3 'title' / 'll titles re the s!e too;'4
- 'hre%' / 'so!ething0e".ht!l'
(
+);
)his time, we broke the ob(ect up into multiple lines. Remember, whitespace doesn't
matter in $ava%cript, so you should feel free to use it liberally to make your code more
legible+ #ou can use a minification tool later to strip out unnecessary whitespace for
production.
Example 3.23: Getting attributes
1
L('').ttr('hre%'); // returns the hre% %or the %irst ele!ent in
the docu!ent
-raversing
3nce you have a ./uery selection& you can %ind other elements using your selection as a
starting point"
,or complete documentation o% ./uery traversal methods&
visit http4KKapi".2uery"comKcategoryKtraversingK"
Note
7e cautious (ith traversing long distances in your documents L comple' traversal maes it
imperative that your documentIs structure remain the same& something thatIs di%%icult to
guarantee even i% youIre the one creating the (hole application %rom server to client" 3ne-
or t(o-step traversal is %ine& but you generally (ant to avoid traversals that tae you %rom
one container to another"
Example 3.24: Moving around the DOM using traversal methods
1 L('h1').next('p');
2 L('di$/$isi,le').prent();
3 L('input=n!e=%irstPn!e>').closest('%or!');
- L('O!ySist').children();
(
L('li.selected').si,lings();
$ou can also iterate over a selection using H"%n"each" -his method iterates over all o% the
elements in a selection& and runs a %unction %or each one" -he %unction receives the inde' o%
the current element and the D3M element itsel% as arguments" +nside the %unction& the
D3M element is also available as this by de%ault"
Example 3.25: Iterating over a selection
1 L('O!ySist li').ech(%unction(idx4 el) *
2 console.log(
3 'Ele!ent ' ' idx '
- 'hs the %ollo"ing ht!l/ ' '
( L(el).ht!l()
) );
5
+);
Manipulating :lements
3nce youIve made a selection& the %un begins" $ou can change& move& remove& and clone
elements" $ou can also create ne( elements via a simple synta'"
,or complete documentation o% ./uery manipulation methods&
visit http4KKapi".2uery"comKcategoryKmanipulationK"
Getting and Setting Information about Elements
-here are any number o% (ays you can change an e'isting element" Among the most
common tass youIll per%orm is changing the inner *-ML or attribute o% an element"
./uery o%%ers simple& cross-bro(ser methods %or these sorts o% manipulations" $ou can also
get in%ormation about elements using many o% the same methods in their getter
incarnations" 5eIll see e'amples o% these throughout this section& but speci%ically& here are
a %e( methods you can use to get and set in%ormation about elements"
Note
Changing things about elements is trivial& but remember that the change (ill
a%%ect all elements in the selection& so i% you .ust (ant to change one element& be sure to
speci%y that in your selection be%ore calling a setter method"
Note
5hen methods act as getters& they generally only (or on the %irst element in the selection&
and they do not return a ./uery ob.ect& so you canIt chain additional methods to them" 3ne
notable e'ception is H"%n"te't0 as mentioned belo(& it gets the te't %or all elements in the
selection"
$.fn.html
)et or set the html contents"
$.fn.text
)et or set the te't contents0 *-ML (ill be stripped"
$.fn.attr
)et or set the value o% the provided attribute"
$.fn.width
)et or set the (idth in pi'els o% the %irst element in the selection as an integer"
$.fn.height
)et or set the height in pi'els o% the %irst element in the selection as an integer"
$.fn.position
)et an ob.ect (ith position in%ormation %or the %irst element in the selection& relative
to its %irst positioned ancestor" -his is a getter only"
$.fn.val
)et or set the value o% %orm elements"
Example 3.26: Changing the HTML of an element
1 L('O!yCi$ p/%irst')
2
.ht!l('0e" <strong>%irst</strong> prgrph;');
Moving& Copying& and Removing :lements
-here are a variety o% (ays to move elements around the D3M0 generally& there are t(o
approaches4
>lace the selected elementAsB relative to another element
>lace an element relative to the selected elementAsB
,or e'ample& ./uery provides H"%n"insertA%ter and H"%n"a%ter" -he H"%n"insertA%ter method
places the selected elementAsB a%ter the element that you provide as an argument0
the H"%n"a%ter method places the element provided as an argument a%ter the selected
element" Several other methods %ollo( this
pattern4 H"%n"insert7e%ore and H"%n"be%ore0 H"%n"append-o and H"%n"append0
and H"%n"prepend-o and H"%n"prepend"
-he method that maes the most sense %or you (ill depend on (hat elements you already
have selected& and (hether you (ill need to store a re%erence to the elements youIre adding
to the page" +% you need to store a re%erence& you (ill al(ays (ant to tae the %irst approach
L placing the selected elements relative to another element L as it returns the elementAsB
youIre placing" +n this case& H"%n"insertA%ter& H"%n"insert7e%ore& H"%n"append-o&
and H"%n"prepend-o (ill be your tools o% choice"
Example 3.27: Moving elements using different approaches
1 // !#e the %irst list ite! the lst list ite!
2 $r Lli = L('O!ySist li/%irst').ppendBo('O!ySist');
3
- // nother pproch to the s!e pro,le!
( L('O!ySist').ppend(L('O!ySist li/%irst'));
)
5 // note tht there's no "y to ccess the
6 // list ite! tht "e !o$ed4 s this returns
8
// the list itsel%
Cloning :lements
5hen you use methods such as H"%n"append-o& you are moving the element0 sometimes
you (ant to mae a copy o% the element instead" +n this case& youIll need to use H"%n"clone
%irst"
Example 3.28: Making a copy of an element
1 // copy the %irst list ite! to the end o% the list
2
L('O!ySist li/%irst').clone().ppendBo('O!ySist');
Cote
+% you need to copy related data and events& be sure to pass true as an argument
to H"%n"clone"
Removing Elements
-here are t(o (ays to remove elements %rom the page4 H"%n"remove and H"%n"detach" $ouIll
use H"%n"remove (hen you (ant to permanently remove the selection %rom the page0 (hile
the method does return the removed elementAsB& those elements (ill not have their
associated data and events attached to them i% you return them to the page"
+% you need the data and events to persist& youIll (ant to use H"%n"detach instead"
Lie H"%n"remove& it returns the selection& but it also maintains the data and events
associated (ith the selection& so you can restore the selection to the page at a later time"
Note
-he H"%n"detach method is e'tremely valuable i% you are doing heavy manipulation to an
element" +n that case& itIs bene%icial to H"%n"detach the element %rom the page& (or on it in
your code& and then restore it to the page (hen youIre done" -his saves you %rom e'pensive
FD3M touchesF (hile maintaining the elementIs data and events"
+% you (ant to leave the element on the page but simply (ant to remove its contents& you
can use H"%n"empty to dispose o% the elementIs inner *-ML"
Creating New Elements
./uery o%%ers a trivial and elegant (ay to create ne( elements using the same HAB method
you use to mae selections"
Example 3.29: Creating new elements
1 L('<p>Bhis is ne" prgrph</p>');
2
L('<li clss=@ne"@>ne" list ite!</li>');
:'ample !"!04 Creating a ne( element (ith an attribute ob.ect
1 L('</>'4 *
2 ht!l / 'Bhis is <strong>ne"</strong> lin#'4
3 'clss' / 'ne"'4
- hre% / '%oo.ht!l'
&ote that in the attributes ob(ect we included as the second argument, the property name
class is ,uoted, while the property names te!t and href are not. -roperty names
generally do not need to be ,uoted unless they are reserved words .as class is in this
case/.
5hen you create a ne( element& it is not immediately added to the page" -here are several
(ays to add an element to the page once itIs been created"
Example 3.31: Getting a new element on to the page
1 $r L!y0e"Ele!ent = L('<p>0e" ele!ent</p>');
2 L!y0e"Ele!ent.ppendBo('Ocontent');
3
-
L!y0e"Ele!ent.insertG%ter('ul/lst'); // this "ill re!o$e the p %ro!
Ocontent;
(
L('ul').lst().%ter(L!y0e"Ele!ent.clone()); // clone the p so no" "e
h$e 2
%trictly speaking, you don't have to store the created element in a variable ' you could
(ust call the method to add the element to the page directly after the 0./. 1owever, most
of the time you will want a reference to the element you added, so you don't need to select
it later.
$ou can even create an element as youIre adding it to the page& but note that in this case
you donIt get a re%erence to the ne(ly created element"
Example 3.32: Creating and adding an element to the page at the same time
1
L('ul').ppend('<li>list ite!</li>');
Cote
-he synta' %or adding ne( elements to the page is so easy& itIs tempting to %orget that
thereIs a huge per%ormance cost %or adding to the D3M repeatedly" +% you are adding many
elements to the same container& youIll (ant to concatenate all the html into a single string&
and then append that string to the container instead o% appending the elements one at a
time" $ou can use an array to gather all the pieces together& then .oin them into a single
string %or appending"
1 $r !y<te!s = =>4 L!ySist = L('O!ySist');
2
3 %or ($r i=1; i<111; i'') *
- !y<te!s.push('<li>ite! ' ' i ' '</li>');
( +
)
5 L!ySist.ppend(!y<te!s.join(''));
Manipulating Attributes
./ueryIs attribute manipulation capabilities are e'tensive" 7asic changes are simple& but
the H"%n"attr method also allo(s %or more comple' manipulations" +t can either set an
e'plicit value& or set a value using the return value o% a %unction" 5hen the %unction synta'
is used& the %unction receives t(o arguments4 the @ero-based inde' o% the element (hose
attribute is being changed& and the current value o% the attribute being changed"
Example 3.33: Manipulating a single attribute
1
L('O!yCi$ /%irst').ttr('hre%'4 'ne"Cestintion.ht!l');
:'ample !"!84 Manipulating multiple attributes
1 L('O!yCi$ /%irst').ttr(*
2 hre% / 'ne"Cestintion.ht!l'4
3 rel / 'super.specil'
-
+);
:'ample !"!94 #sing a %unction to determine an attributeIs ne( value
11 L('O!yCi$ /%irst').ttr(*
12 rel / 'super.specil'4
13 hre% / %unction(idx4 hre%) *
1- return '/ne"/' ' hre%;
1( +
1) +);
15
16 L('O!yCi$ /%irst').ttr('hre%'4 %unction(idx4 hre%) *
18 return '/ne"/' ' hre%;
11
+);
:'ercises
Selecting
3pen the %ile Ke'ercisesKinde'"html in your bro(ser" #se the
%ile Ke'ercisesK.sKsandbo'".s or (or in ,irebug to accomplish the %ollo(ing4
1" Select all o% the div elements that have a class o% FmoduleF"
2" Come up (ith three selectors that you could use to get the third item in the MmyList
unordered list" 5hich is the best to useG 5hyG
!" Select the label %or the search input using an attribute selector"
8" ,igure out ho( many elements on the page are hidden Ahint4 "lengthB"
9" ,igure out ho( many image elements on the page have an alt attribute"
;" Select all o% the odd table ro(s in the table body"
Traversing
3pen the %ile Ke'ercisesKinde'"html in your bro(ser" #se the
%ile Ke'ercisesK.sKsandbo'".s or (or in ,irebug to accomplish the %ollo(ing4
1" Select all o% the image elements on the page0 log each imageIs alt attribute"
2" Select the search input te't bo'& then traverse up to the %orm and add a class to the
%orm"
!" Select the list item inside MmyList that has a class o% FcurrentF and remove that class
%rom it0 add a class o% FcurrentF to the ne't list item"
8" Select the select element inside Mspecials0 traverse your (ay to the submit button"
9" Select the %irst list item in the Mslidesho( element0 add the class FcurrentF to it& and
then add a class o% FdisabledF to its sibling elements"
Manipulating
3pen the %ile Ke'ercisesKinde'"html in your bro(ser" #se the
%ile Ke'ercisesK.sKsandbo'".s or (or in ,irebug to accomplish the %ollo(ing4
1" Add %ive ne( list items to the end o% the unordered list MmyList" *int4
1 %or ($r i = 1; i<(; i'') * ... +
2" Remove the odd list items
!" Add another h2 and another paragraph to the last div"module
8" Add another option to the select element0 give the option the value F5ednesdayF
9" Add a ne( div"module to the page a%ter the last one0 put a copy o% one o% the e'isting
images inside o% it"
7ac to top
jQuery Core
$ vs $()
#ntil no(& (e1ve been dealing entirely (ith methods that are called on a ./uery ob.ect" ,or
e'ample4
1 L('h1').re!o$e();
Most ./uery methods are called on ./uery ob.ects as sho(n above0 these methods are said
to be part o% the H"%n namespace& or the P./uery prototype&Q and are best thought o% as
./uery ob.ect methods"
*o(ever& there are several methods that do not act on a selection0 these methods are said
to be part o% the ./uery namespace& and are best thought o% as core ./uery methods"
-his distinction can be incredibly con%using to ne( ./uery users" *ere1s (hat you need to
remember4
Methods called on ./uery selections are in the H"%n namespace& and automatically
receive and return the selection as this"
Methods in the H namespace are generally utility-type methods& and do not (or
(ith selections0 they are not automatically passed any arguments& and their return
value (ill vary"
-here are a %e( cases (here ob.ect methods and core methods have the same names& such
as H"each and H"%n"each" +n these cases& be e'tremely care%ul (hen reading the
documentation that you are e'ploring the correct method"
Utility Methods
./uery o%%ers several utility methods in the H namespace" -hese methods are help%ul %or
accomplishing routine programming tass" 7elo( are e'amples o% a %e( o% the utility
methods0 %or a complete re%erence on ./uery utility methods&
visit http4KKapi".2uery"comKcategoryKutilitiesK"
$.trim
Removes leading and trailing (hitespace"
1 L.tri!(' lots o% extr "hitespce ');
2 // returns 'lots o% extr "hitespce'
$.each
+terates over arrays and ob.ects"
1 L.ech(= '%oo'4 ',r'4 ',2' >4 %unction(idx4 $l) *
2 console.log('ele!ent ' ' idx ' 'is ' ' $l);
3 +);
-
( L.ech(* %oo / ',r'4 ,2 / ',i!' +4 %unction(#4 $) *
) console.log(# ' ' / ' ' $);
5 +);
Cote
-here is also a method H"%n"each& (hich is used %or iterating over a selection o%
elements"
$.inArray
Returns a valueIs inde' in an array& or -1 i% the value is not in the array"
1 $r !yGrry = = 14 24 34 ( >;
2
3 i% (L.inGrry(-4 !yGrry) ;== .1) *
- console.log('%ound it;');
( +
$.extend
Changes the properties o% the %irst ob.ect using the properties o% subse2uent ob.ects"
1 $r %irstH,ject = * %oo / ',r'4 / ',' +;
2 $r secondH,ject = * %oo / ',2' +;
3
- $r ne"H,ject = L.extend(%irstH,ject4 secondH,ject);
( console.log(%irstH,ject.%oo); // ',2'
) console.log(ne"H,ject.%oo); // ',2'
+% you donIt (ant to change any o% the ob.ects you pass to H"e'tend& pass an empty
ob.ect as the %irst argument"
1 $r %irstH,ject = * %oo / ',r'4 / ',' +;
2 $r secondH,ject = * %oo / ',2' +;
3
- $r ne"H,ject = L.extend(*+4 %irstH,ject4 secondH,ject);
( console.log(%irstH,ject.%oo); // ',r'
) console.log(ne"H,ject.%oo); // ',2'
$.proxy
Returns a %unction that (ill al(ays run in the provided scope L that is& sets the
meaning o% this inside the passed %unction to the second argument"
1 $r !yJunction = %unction() * console.log(this); +;
2 $r !yH,ject = * %oo / ',r' +;
3
- !yJunction(); // logs "indo" o,ject
(
) $r !yTroxyJunction = L.proxy(!yJunction4 !yH,ject);
5 !yTroxyJunction(); // logs !yH,ject o,ject
+% you have an ob.ect (ith methods& you can pass the ob.ect and the name o% a
method to return a %unction that (ill al(ays run in the scope o% the ob.ect"
1 $r !yH,ject = *
2 !yJn / %unction() *
3 console.log(this);
- +
( +;
)
5 L('O%oo').clic#(!yH,ject.!yJn); // logs CHK ele!ent O%oo
6 L('O%oo').clic#(L.proxy(!yH,ject4 '!yJn')); // logs !yH,ject
Checing types
As mentioned in the F6avaScript basicsF section& ./uery o%%ers a %e( basic utility methods
%or determining the type o% a speci%ic value"
Example 4.1: Checking the type of an arbitrary value
11 $r !yUlue = =14 24 3>;
12
13 // Vsing ?$9cript's typeo% opertor to test %or pri!ti$e types
1- typeo% !yUlue == 'string'; // %lse
1( typeo% !yUlue == 'nu!,er'; // %lse
1) typeo% !yUlue == 'unde%ined'; // %lse
15 typeo% !yUlue == ',oolen'; // %lse
16
18 // Vsing strict equlity opertor to chec# %or null
11 !yUlue === null; // %lse
11
12 // Vsing jQuery's !ethods to chec# %or non.pri!ti$e types
13 jQuery.isJunction(!yUlue); // %lse
1- jQuery.isTlinH,ject(!yUlue); // %lse
1(
jQuery.isGrry(!yUlue); // true
Data Methods
As your (or (ith ./uery progresses& youIll %ind that thereIs o%ten data about an element
that you (ant to store (ith the element" +n plain 6avaScript& you might do this by adding a
property to the D3M element& but youId have to deal (ith memory leas in some bro(sers"
./uery o%%ers a straight%or(ard (ay to store data related to an element& and it manages the
memory issues %or you"
Example 4.2: Storing and retrieving data related to an element
1 L('O!yCi$').dt('#ey0!e'4 * %oo / ',r' +);
2
L('O!yCi$').dt('#ey0!e'); // * %oo / ',r' +
$ou can store any ind o% data on an element& and itIs hard to overstate the importance o%
this (hen you get into comple' application development" ,or the purposes o% this class&
(eIll mostly use H"%n"data to store re%erences to other elements"
,or e'ample& (e may (ant to establish a relationship bet(een a list item and a div thatIs
inside o% it" 5e could establish this relationship every single time (e interact (ith the list
item& but a better solution (ould be to establish the relationship once& and then store a
pointer to the div on the list item using H"%n"data4
Example 4.3: Storing a relationship between elements using $.fn.data
1 L('O!ySist li').ech(%unction() *
2 $r Lli = L(this)4 Ldi$ = Lli.%ind('di$.content');
3 Lli.dt('contentCi$'4 Ldi$);
- +);
(
) // lter4 "e don't h$e to %ind the di$ gin;
5 // "e cn just red it %ro! the list ite!'s dt
6 $r L%irstSi = L('O!ySist li/%irst');
8
L%irstSi.dt('contentCi$').ht!l('ne" content');
+n addition to passing H"%n"data a single ey-value pair to store data& you can also pass an
ob.ect containing one or more pairs"
Feature & Browser Detection
Although ./uery eliminates most 6avaScript bro(ser 2uirs& there are still occasions (hen
your code needs to no( about the bro(ser environment"
./uery o%%ers the H"support ob.ect& as (ell as the deprecated H"bro(ser ob.ect& %or this
purpose" ,or complete documentation on these ob.ects&
visithttp4KKapi".2uery"comK./uery"supportK and http4KKapi".2uery"comK./uery"bro(serK"
-he H"support ob.ect is dedicated to determining (hat %eatures a bro(ser supports0 it is
recommended as a more P%uture-proo%Q method o% customi@ing your 6avaScript %or
di%%erent bro(ser environments"
-he H"bro(ser ob.ect (as deprecated in %avor o% the H"support ob.ect& but it (ill not be
removed %rom ./uery anytime soon" +t provides direct detection o% the bro(ser brand and
version"
Avoiding Conflicts with Other Libraries
+% you are using another 6avaScript library that uses the H variable& you can run into
con%licts (ith ./uery" +n order to avoid these con%licts& you need to put ./uery in no-
con%lict mode immediately a%ter it is loaded onto the page and be%ore you attempt to use
./uery in your page"
5hen you put ./uery into no-con%lict mode& you have the option o% assigning a variable
name to replace H"
Example 4.4: Putting jQuery into no-conflict mode
1 <script src=@prototype.js@></script>
2 <script src=@jquery.js@></script>
3
<script>$r Lj = jQuery.noDon%lict();</script>
$ou can continue to use the standard H by (rapping your code in a sel%-e'ecuting
anonymous %unction0 this is a standard pattern %or plugin authoring& (here the author
cannot no( (hether another library (ill have taen over the H"
Example 4.5: Using the $ inside a self-executing anonymous function
1 <script src=@prototype.js@></script>
2 <script src=@jquery.js@></script>
3 <script>
- jQuery.noDon%lict();
(
) (%unction(L) *
5 // your code here4 using the L
6 +)(jQuery);
8
</script>
7ac to top
Events
Overview
./uery provides simple methods %or attaching event handlers to selections" 5hen an event
occurs& the provided %unction is e'ecuted" +nside the %unction& this re%ers to the element
that (as cliced"
,or details on ./uery events& visit http4KKapi".2uery"comKcategoryKeventsK"
-he event handling %unction can receive an event ob.ect" -his ob.ect can be used to
determine the nature o% the event& and to prevent the event1s de%ault behavior"
,or details on the event ob.ect& visit http4KKapi".2uery"comKcategoryKeventsKevent-ob.ectK"
Connecting Events to Elements
./uery o%%ers convenience methods %or most common events& and these are the methods
you (ill see used most o%ten" -hese methods L including H"%n"clic&
H"%n"%ocus& H"%n"blur& H"%n"change& etc" L are shorthand %or ./ueryIs H"%n"bind method" -he
bind method is use%ul %or binding the same handler %unction to multiple events& (hen you
(ant to provide data to the event hander& (hen you are (oring (ith custom events& or
(hen you (ant to pass an ob.ect o% multiple events and handlers"
Example 5.1: Event binding using a convenience method
1 L('p').clic#(%unction() *
2 console.log('clic#');
3
+);
:'ample 9"24 :vent biding using the H"%n"bind method
1 L('p').,ind('clic#'4 %unction() *
2 console.log('clic#');
3
+);
:'ample 9"!4 :vent binding using the H"%n"bind method (ith data
1 L('input').,ind(
2 'clic# chnge'4 // ,ind to !ultiple e$ents
3 * %oo / ',r' +4 // pss in dt
-
( %unction(e$entH,ject) *
) console.log(e$entH,ject.type4 e$entH,ject.dt);
5 // logs e$ent type4 then * %oo / ',r' +
6 +
8
);
Connecting :vents to Run 3nly 3nce
Sometimes you need a particular handler to run only once L a%ter that& you may (ant no
handler to run& or you may (ant a di%%erent handler to run" ./uery provides
the H"%n"one method %or this purpose"
Example 5.4: Switching handlers using the $.fn.one method
1 L('p').one('clic#'4 %unction() *
2 console.log('Wou just clic#ed this %or the %irst ti!e;');
3
L(this).clic#(%unction() * console.log('Wou h$e clic#ed this
,e%ore;'); +);
-
+);
-he H"%n"one method is especially use%ul i% you need to do some complicated setup the %irst
time an element is cliced& but not subse2uent times"
Disconnecting Events
-o disconnect an event handler& you use the H"%n"unbind method and pass in the event type
to unbind" +% you attached a named %unction to the event& then you can isolate the
unbinding to that named %unction by passing it as the second argument"
Example 5.5: Unbinding all click handlers on a selection
1
L('p').un,ind('clic#');
:'ample 9";4 #nbinding a particular clic handler
1 $r %oo = %unction() * console.log('%oo'); +;
2 $r ,r = %unction() * console.log(',r'); +;
3
- L('p').,ind('clic#'4 %oo).,ind('clic#'4 ,r);
(
L('p').un,ind('clic#'4 ,r); // %oo is still ,ound to the clic# e$ent
Camespacing :vents
,or comple' applications and %or plugins you share (ith others& it can be use%ul to
namespace your events so you donIt unintentionally disconnect events that you didnIt or
couldnIt no( about"
Example 5.7: Namespacing events
1 L('p').,ind('clic#.!y0!espce'4 %unction() * /& ... &/ +);
2 L('p').un,ind('clic#.!y0!espce');
3
L('p').un,ind('.!y0!espce'); // un,ind ll e$ents in the n!espce
7inding Multiple :vents
/uite o%ten elements in your application (ill be bound to multiple events& each having a
di%%erent %unction %or handing the event" +n these cases you can pass an ob.ect
into H"%n"bind (ith one or more eyKvalue pairs& (ith the ey being the event name and the
value being the %unction to handle the event"
Example 5.8: Binding Multiple Events
1 L('p').,ind(*
2 'clic#'/ %unction() * console.log('clic#ed;'); +4
3 '!ouseo$er'/ %unction() * console.log('ho$ered;'); +
-
+);
Cote
-he option to pass an ob.ect o% multiple events and handlers to H"%n"bind (as introduced in
./uery 1"8"8"
+nside the :vent *andling ,unction
As mentioned in the overvie(& the event handling %unction receives an event ob.ect& (hich
contains many properties and methods" -he event ob.ect is most commonly used to
prevent the de%ault action o% the event via the preventDe%ault method" *o(ever& the event
ob.ect contains a number o% other use%ul properties and methods& including4
pageX, pageY
-he mouse position at the time the event occurred& relative to the top le%t o% the page"
type
-he type o% the event Ae"g" FclicFB"
which
-he button or ey that (as pressed"
data
Any data that (as passed in (hen the event (as bound"
target
-he D3M element that initiated the event"
preventDefault()
>revent the de%ault action o% the event Ae"g" %ollo(ing a linB"
stopPropagation()
Stop the event %rom bubbling up to other elements"
+n addition to the event ob.ect& the event handling %unction also has access to the D3M
element that the handler (as bound to via the ey(ord this" -o turn the D3M element into
a ./uery ob.ect that (e can use ./uery methods on& (e simply do HAthisB& o%ten %ollo(ing
this idiom4
1 $r Lthis = L(this);
Preventing a link from being followed
1 L('').clic#(%unction(e) *
2 $r Lthis = L(this);
3 i% (Lthis.ttr('hre%').!tch('e$il')) *
- e.pre$entCe%ult();
( Lthis.ddDlss('e$il');
) +
5
+);
-riggering :vent *andlers
./uery provides a (ay to trigger the event handlers bound to an element (ithout any user
interaction via the H"%n"trigger method" 5hile this method has its uses& it should not be
used simply to call a %unction that (as bound as a clic handler" +nstead& you should store
the %unction you (ant to call in a variable& and pass the variable name (hen you do your
binding" -hen& you can call the %unction itsel% (henever you (ant& (ithout the need
%or H"%n"trigger"
Triggering an event handler the right way
11 $r %oo = %unction(e) *
12 i% (e) *
13 console.log(e);
1- + else *
1( console.log('this didnX't co!e %ro! n e$ent;');
1) +
15 +;
16
18
11 L('p').clic#(%oo);
11
12
%oo(); // insted o% L('p').trigger('clic#')
+ncreasing >er%ormance (ith :vent Delegation
$ouIll %re2uently use ./uery to add ne( elements to the page& and (hen you do& you may
need to bind events to those ne( elements L events you already bound to similar elements
that (ere on the page originally" +nstead o% repeating your event binding every time you
add elements to the page& you can use event delegation" 5ith event delegation& you bind
your event to a container element& and then (hen the event occurs& you loo to see (hich
contained element it occurred on" +% this sounds complicated& lucily ./uery maes it easy
(ith its H"%n"live and H"%n"delegate methods"
5hile most people discover event delegation (hile dealing (ith elements added to the
page later& it has some per%ormance bene%its even i% you never add more elements to the
page" -he time re2uired to bind event handlers to hundreds o% individual elements is non-
trivial0 i% you have a large set o% elements& you should consider delegating related events to
a container element"
Note
-he H"%n"live method (as introduced in ./uery 1"!& and at that time only certain event
types (ere supported" As o% ./uery 1"8"2& the H"%n"delegate method is available& and is the
pre%erred method"
Event delegation using $.fn.delegate
1 L('O!yVnorderedSist').delegte('li'4 'clic#'4 %unction(e) *
2 $r L!ySist<te! = L(this);
3 // ...
-
+);
Event delegation using $.fn.live
1 L('O!yVnorderedSist li').li$e('clic#'4 %unction(e) *
2 $r L!ySist<te! = L(this);
3 // ...
-
+);
#nbinding Delegated :vents
+% you need to remove delegated events& you canIt simply unbind them" +nstead&
use H"%n"undelegate %or events connected (ith H"%n"delegate& and H"%n"die %or events
connected (ith H"%n"live" As (ith bind& you can optionally pass in the name o% the bound
%unction"
Unbinding delegated events
1 L('O!yVnorderedSist').undelegte('li'4 'clic#');
2
L('O!yVnorderedSist li').die('clic#');
:vent *elpers
./uery o%%ers t(o event-related helper %unctions that save you a %e( eystroes"
$.fn.hover
-he H"%n"hover method lets you pass one or t(o %unctions to be run (hen
the mouseenter and mouseleave events occur on an element" +% you pass one %unction& it
(ill be run %or both events0 i% you pass t(o %unctions& the %irst (ill run %or mouseenter& and
the second (ill run %or mouseleave"
Note
>rior to ./uery 1"8& the H"%n"hover method re2uired t(o %unctions"
The hover helper function
1 L('O!enu li').ho$er(%unction() *
2 L(this).toggleDlss('ho$er');
3
+);
H"%n"toggle
-he H"%n"toggle method is triggered by the FclicF event and accepts t(o or more %unctions"
:ach time the clic event occurs& the ne't %unction in the list is called"
)enerally& H"%n"toggle is used (ith .ust t(o %unctions0 ho(ever& it (ill accept an unlimited
number o% %unctions" 7e care%ul& though4 providing a long list o% %unctions can be di%%icult
to debugB"
The toggle helper function
1 L('p.expnder').toggle(
2 %unction() *
3 L(this).pre$().ddDlss('open');
- +4
( %unction() *
) L(this).pre$().re!o$eDlss('open');
5 +
6
);
:'ercises
Create an Input Hint
3pen the %ile Ke'ercisesKinde'"html in your bro(ser" #se the
%ile Ke'ercisesK.sKinput*int".s or (or in ,irebug" $our tas is to use the te't o% the label
%or the search input to create FhintF te't %or the search input" -he steps are as %ollo(s4
1" Set the value o% the search input to the te't o% the label element
2" Add a class o% FhintF to the search input
!" Remove the label element
8" 7ind a %ocus event to the search input that removes the hint te't and the FhintF class
9" 7ind a blur event to the search input that restores the hint te't and FhintF class i% no
search te't (as entered
5hat other considerations might there be i% you (ere creating this %unctionality %or a real
siteG
Add Tabbed Navigation
3pen the %ile Ke'ercisesKinde'"html in your bro(ser" #se the %ile Ke'ercisesK.sKtabs".s" $our
tas is to create tabbed navigation %or the t(o div"module elements" -o accomplish this4
1" *ide all o% the modules"
2" Create an unordered list element be%ore the %irst module"
3. +terate over the modules using H"%n"each" ,or each module& use the te't o% the h2
element as the te't %or a list item that you add to the unordered list element"
8" 7ind a clic event to the list item that4
Sho(s the related module& and hides any other modules
Adds a class o% FcurrentF to the cliced list item
Removes the class FcurrentF %rom the other list item
9" ,inally& sho( the %irst tab"
Back to top
Effects
Overview
./uery maes it trivial to add simple e%%ects to your page" :%%ects can use the built-in
settings& or provide a customi@ed duration" $ou can also create custom animations o%
arbitrary CSS properties"
,or complete details on ./uery e%%ects& visit http4KKapi".2uery"comKcategoryKe%%ectsK"
Built-in Effects
,re2uently used e%%ects are built into ./uery as methods4
$.fn.show
Sho( the selected element"
$.fn.hide
*ide the selected elements"
$.fn.fadeIn
Animate the opacity o% the selected elements to 100Z"
$.fn.fadeOut
Animate the opacity o% the selected elements to 0Z"
$.fn.slideDown
Display the selected elements (ith a vertical sliding motion"
$.fn.slideUp
*ide the selected elements (ith a vertical sliding motion"
$.fn.slideToggle
Sho( or hide the selected elements (ith a vertical sliding motion& depending on
(hether the elements are currently visible"
Example 6.1: A basic use of a built-in effect
1
L('h1').sho"();
Changing the Duration o% 7uilt-in :%%ects
5ith the e'ception o% H"%n"sho( and H"%n"hide& all o% the built-in methods are animated
over the course o% 800ms by de%ault" Changing the duration o% an e%%ect is simple"
Example 6.2: Setting the duration of an effect
1 L('h1').%de<n(311); // %de in o$er 311!s
2
L('h1').%deHut('slo"'); // using ,uilt.in speed de%inition
./uery"%'"speeds
./uery has an ob.ect at ./uery"%'"speeds that contains the de%ault speed& as (ell as settings
%or Fslo(F and F%astF"
1 speeds/ *
2 slo"/ )114
3 %st/ 2114
- // Ce%ult speed
( Pde%ult/ -11
) +
+t is possible to override or add to this ob.ect" ,or e'ample& you may (ant to change the
de%ault duration o% e%%ects& or you may (ant to create your o(n e%%ects speed"
Example 6.3: Augmenting jQuery.fx.speeds with custom speed definitions
1 jQuery.%x.speeds.,l2ing = 111;
2
jQuery.%x.speeds.turtle = 2111;
Doing Something (hen an :%%ect is Done
3%ten& youIll (ant to run some code once an animation is done L i% you run it be%ore the
animation is done& it may a%%ect the 2uality o% the animation& or it may remove elements
that are part o% the animation" RDe%inition4 Callbac %unctions provide a (ay to register
your interest in an event that (ill happen in the %uture"S+n this case& the event (eIll be
responding to is the conclusion o% the animation" +nside o% the callbac %unction& the
ey(ord this re%ers to the element that the e%%ect (as called on0 as (e did inside o% event
handler %unctions& (e can turn it into a ./uery ob.ect via HAthisB"
Example 6.4: Running code when an animation is complete
1
L('di$.old').%deHut(3114 %unction() * L(this).re!o$e(); +);
Cote that i% your selection doesnIt return any elements& your callbac (ill never runJ $ou
can solve this problem by testing (hether your selection returned any elements0 i% not& you
can .ust run the callbac immediately"
Example 6.5: Run a callback even if there were no elements to animate
11 $r Lthing = L('Ononexistent');
12
13 $r c, = %unction() *
1- console.log('done;');
1( +;
1)
15 i% (Lthing.length) *
16 Lthing.%de<n(3114 c,);
18 + else *
11 c,();
11
+
Custom :%%ects (ith H"%n"animate
./uery maes it possible to animate arbitrary CSS properties via the H"%n"animate method"
-he H"%n"animate method lets you animate to a set value& or to a value relative to the
current value"
Example 6.6: Custom effects with $.fn.animate
1 L('di$.%unti!es').ni!te(
2 *
3 le%t / @'=(1@4
- opcity / 1.2(
( +4
) 3114 // durtion
5 %unction() * console.log('done;'); // cl,c#
6
+);
Cote
Color-related properties cannot be animated (ith H"%n"animate using ./uery out o% the
bo'" Color animations can easily be accomplished by including thecolor plugin" 5eIll
discuss using plugins later in the boo"
Easing
RDe%inition4 :asing describes the manner in (hich an e%%ect occurs L (hether the rate o%
change is steady& or varies over the duration o% the animation"S ./uery includes only t(o
methods o% easing4 s(ing and linear" +% you (ant more natural transitions in your
animations& various easing plugins are available"
As o% ./uery 1"8& it is possible to do per-property easing (hen using the H"%n"animate
method"
Example 6.7: Per-property easing
1 L('di$.%unti!es').ni!te(
2 *
3 le%t / = @'=(1@4 @s"ing@ >4
- opcity / = 1.2(4 @liner@ >
( +4
) 311
5
);
,or more details on easing options& see http4KKapi".2uery"comKanimateK"
Managing Effects
./uery provides several tools %or managing animations"
$.fn.stop
Stop currently running animations on the selected elements"
$.fn.delay
5ait the speci%ied number o% milliseconds be%ore running the ne't animation"
1 L('h1').sho"(311).dely(1111).hide(311);
jQuery.fx.off
+% this value is true& there (ill be no transition %or animations0 elements (ill
immediately be set to the target %inal state instead" -his can be especially use%ul (hen
dealing (ith older bro(sers0 you also may (ant to provide the option to your users"
Exercises
Reveal Hidden Text
3pen the %ile Ke'ercisesKinde'"html in your bro(ser" #se the %ile Ke'ercisesK.sKblog".s"
$our tas is to add some interactivity to the blog section o% the page" -he spec %or the
%eature is as %ollo(s4
Clicing on a headline in the Mblog div should slide do(n the e'cerpt paragraph
Clicing on another headline should slide do(n its e'cerpt paragraph& and slide up
any other currently sho(ing e'cerpt paragraphs"
*int4 donIt %orget about the 4visible selectorJ
Create Dropdown Menus
3pen the %ile Ke'ercisesKinde'"html in your bro(ser" #se the
%ile Ke'ercisesK.sKnavigation".s" $our tas is to add dropdo(ns to the main navigation at
the top o% the page"
*overing over an item in the main menu should sho( that itemIs submenu items& i%
any"
:'iting an item should hide any submenu items"
-o accomplish this& use the H"%n"hover method to add and remove a class %rom the
submenu items to control (hether theyIre visible or hidden" A-he %ile
atKe'ercisesKcssKstyles"css includes the FhoverF class %or this purpose"B
Create a Slideshow
3pen the %ile Ke'ercisesKinde'"html in your bro(ser" #se the
%ile Ke'ercisesK.sKslidesho(".s" $our tas is to tae a plain semantic *-ML page and
enhance it (ith 6avaScript by adding a slidesho("
1" Move the Mslidesho( element to the top o% the body"
2" 5rite code to cycle through the list items inside the element0 %ade one in& display it
%or a %e( seconds& then %ade it out and %ade in the ne't one"
!" 5hen you get to the end o% the list& start again at the beginning"
,or an e'tra challenge& create a navigation area under the slidesho( that sho(s ho( many
images there are and (hich image youIre currently vie(ing" A*int4 H"%n"prevAll (ill come
in handy %or this"B
7ac to top
Ajax
Overview
-he [ML*ttpRe2uest method A[*RB allo(s bro(sers to communicate (ith the server
(ithout re2uiring a page reload" -his method& also no(n as A.a' AAsynchronous
6avaScript and [MLB& allo(s %or (eb pages that provide rich& interactive e'periences"
A.a' re2uests are triggered by 6avaScript code0 your code sends a re2uest to a #RL& and
(hen it receives a response& a callbac %unction can be triggered to handle the response"
7ecause the re2uest is asynchronous& the rest o% your code continues to e'ecute (hile the
re2uest is being processed& so it1s imperative that a callbac be used to handle the
response"
./uery provides A.a' support that abstracts a(ay pain%ul bro(ser di%%erences" +t o%%ers
both a %ull-%eatured H"a.a'AB method& and simple convenience methods such
as H"getAB& H"getScriptAB& H"get6S3CAB& H"postAB& and HAB"loadAB"
Most ./uery applications don1t in %act use [ML& despite the name PA.a'Q0 instead& they
transport data as plain *-ML or 6S3C A6avaScript 3b.ect CotationB"
+n general& A.a' does not (or across domains" :'ceptions are services that provide
6S3C> A6S3C (ith >addingB support& (hich allo( limited cross-domain %unctionality"
Key Concepts
>roper use o% A.a'-related ./uery methods re2uires understanding some ey concepts
%irst"
GET vs. Post
-he t(o most common PmethodsQ %or sending a re2uest to a server are ):- and >3S-" +t1s
important to understand the proper application o% each"
-he ):- method should be used %or non-destructive operations L that is& operations
(here you are only PgettingQ data %rom the server& not changing data on the server" ,or
e'ample& a 2uery to a search service might be a ):- re2uest" ):- re2uests may be cached
by the bro(ser& (hich can lead to unpredictable behavior i% you are not e'pecting it" ):-
re2uests generally send all o% their data in a 2uery string"
-he >3S- method should be used %or destructive operations L that is& operations (here
you are changing data on the server" ,or e'ample& a user saving a blog post should be a
>3S- re2uest" >3S- re2uests are generally not cached by the bro(ser0 a 2uery string can
be part o% the #RL& but the data tends to be sent separately as post data"
Data Types
./uery generally re2uires some instruction as to the type o% data you e'pect to get bac
%rom an A.a' re2uest0 in some cases the data type is speci%ied by the method name& and in
other cases it is provided as part o% a con%iguration ob.ect" -here are several options4
text
,or transporting simple strings
html
,or transporting blocs o% *-ML to be placed on the page
script
,or adding a ne( script to the page
json
,or transporting 6S3C-%ormatted data& (hich can include strings& arrays& and ob.ects
Note
As o% ./uery 1"8& i% the 6S3C data sent by your server isnIt properly %ormatted& the
re2uest may %ail silently" See http4KK.son"org %or details on properly %ormatting 6S3C&
but as a general rule& use built-in language methods %or generating 6S3C on the
server to avoid synta' issues"
jsonp
,or transporting 6S3C data %rom another domain
xml
,or transporting data in a custom [ML schema
am a strong proponent of using the $%2& format in most cases, as it provides the most
fle!ibility. t is especially useful for sending both 1)34 and data at the same time.
A is for Asynchronous
-he asynchronicity o% A.a' catches many ne( ./uery users o%% guard" 7ecause A.a' calls
are asynchronous by de%ault& the response is not immediately available" Responses can
only be handled using a callbac" So& %or e'ample& the %ollo(ing code (ill not (or4
1 $r response;
2 L.get('%oo.php'4 %unction(r) * response = r; +);
3 console.log(response); // unde%ined;
+nstead& (e need to pass a callbac %unction to our re2uest0 this callbac (ill run (hen the
re2uest succeeds& at (hich point (e can access the data that it returned& i% any"
1 L.get('%oo.php'4 %unction(response) * console.log(response); +);
Same-3rigin >olicy and 6S3C>
+n general& A.a' re2uests are limited to the same protocol Ahttp or httpsB& the same port&
and the same domain as the page maing the re2uest" -his limitation does not apply to
scripts that are loaded via ./ueryIs A.a' methods"
-he other e'ception is re2uests targeted at a 6S3C> service on another domain" +n the case
o% 6S3C>& the provider o% the service has agreed to respond to your re2uest (ith a script
that can be loaded into the page using a WscriptX tag& thus avoiding the same-origin
limitation0 that script (ill include the data you re2uested& (rapped in a callbac %unction
you provide"
Ajax and Firebug
,irebug Aor the 5ebit +nspector in Chrome or Sa%ariB is an invaluable tool %or (oring
(ith A.a' re2uests" $ou can see A.a' re2uests as they happen in the Console tab o% ,irebug
Aand in the Resources X [*R panel o% 5ebit +nspectorB& and you can clic on a re2uest to
e'pand it and see details such as the re2uest headers& response headers& response content&
and more" +% something isnIt going as e'pected (ith an A.a' re2uest& this is the %irst place
to loo to trac do(n (hatIs (rong"
jQuery's Ajax-Related Methods
5hile ./uery does o%%er many A.a'-related convenience methods& the core H"a.a' method
is at the heart o% all o% them& and understanding it is imperative" 5eIll revie( it %irst& and
then touch brie%ly on the convenience methods"
generally use the 0.a(a! method and do not use convenience methods. 5s you'll see, it
offers features that the convenience methods do not, and its synta! is more easily
understandable, in my opinion.
$.ajax
./uery1s core H"a.a' method is a po(er%ul and straight%or(ard (ay o% creating A.a'
re2uests" +t taes a con%iguration ob.ect that contains all the instructions ./uery re2uires to
complete the re2uest" -he H"a.a' method is particularly valuable because it o%%ers the
ability to speci%y both success and %ailure callbacs" Also& its ability to tae a con%iguration
ob.ect that can be de%ined separately maes it easier to (rite reusable code" ,or complete
documentation o% the con%iguration options& visit http4KKapi".2uery"comK./uery"a.a'K"
Example 7.1: Using the core $.ajax method
11 L.jx(*
12 // the VIS %or the request
13 url / 'post.php'4
1-
1( // the dt to send
1) // ("ill ,e con$erted to query string)
15 dt / * id / 123 +4
16
18 // "hether this is TH9B or YEB request
11 type / 'YEB'4
11
12 // the type o% dt "e expect ,c#
13 dtBype / 'json'4
1-
1( // code to run i% the request succeeds;
1) // the response is pssed to the %unction
15 success / %unction(json) *
16 L('<h1/>').text(json.title).ppendBo(',ody');
18 L('<di$ clss=@content@/>')
21 .ht!l(json.ht!l).ppendBo(',ody');
21 +4
22
23 // code to run i% the request %ils;
2- // the r" request nd sttus codes re
2( // pssed to the %unction
2) error / %unction(xhr4 sttus) *
25 lert('9orry4 there "s pro,le!;');
26 +4
28
31 // code to run regrdless o% success or %ilure
31 co!plete / %unction(xhr4 sttus) *
32 lert('Bhe request is co!plete;');
33 +
+);
Cote
A note about the data-ype setting4 i% the server sends bac data that is in a di%%erent %ormat
than you speci%y& your code may %ail& and the reason (ill not al(ays be clear& because the
*--> response code (ill not sho( an error" 5hen (oring (ith A.a' re2uests& mae sure
your server is sending bac the data type youIre asing %or& and veri%y that the Content-type
header is accurate %or the data type" ,or e'ample& %or 6S3C data& the Content-type header
should beapplicationK.son"
$.ajax Options
-here are many& many options %or the H"a.a' method& (hich is part o% its po(er" ,or a
complete list o% options& visit http4KKapi".2uery"comK./uery"a.a'K0 here are several that you
(ill use %re2uently4
async
Set to %alse i% the re2uest should be sent synchronously" De%aults to true" Cote that i%
you set this option to %alse& your re2uest (ill bloc e'ecution o% other code until the
response is received"
cache
5hether to use a cached response i% available" De%aults to true %or all data-ypes
e'cept FscriptF and F.sonpF" 5hen set to %alse& the #RL (ill simply have a
cachebusting parameter appended to it"
complete
A callbac %unction to run (hen the re2uest is complete& regardless o% success or
%ailure" -he %unction receives the ra( re2uest ob.ect and the te't status o% the re2uest"
context
-he scope in (hich the callbac %unctionAsB should run Ai"e" (hat this (ill mean inside
the callbac %unctionAsBB" 7y de%ault& this inside the callbac %unctionAsB re%ers to the
ob.ect originally passed to H"a.a'"
data
-he data to be sent to the server" -his can either be an ob.ect or a 2uery string& such
as %ooYbarNba@Ybim"
dataType
-he type o% data you e'pect bac %rom the server" 7y de%ault& ./uery (ill loo at the
M+M: type o% the response i% no data-ype is speci%ied"
error
A callbac %unction to run i% the re2uest results in an error" -he %unction receives the
ra( re2uest ob.ect and the te't status o% the re2uest"
jsonp
-he callbac name to send in a 2uery string (hen maing a 6S3C> re2uest" De%aults
to FcallbacF"
success
A callbac %unction to run i% the re2uest succeeds" -he %unction receives the response
data Aconverted to a 6avaScript ob.ect i% the data-ype (as 6S3CB& as (ell as the te't
status o% the re2uest and the ra( re2uest ob.ect"
timeout
-he time in milliseconds to (ait be%ore considering the re2uest a %ailure"
traditional
Set to true to use the param seriali@ation style in use prior to ./uery 1"8" ,or details&
see http4KKapi".2uery"comK./uery"paramK"
type
-he type o% the re2uest& F>3S-F or F):-F" De%aults to F):-F" 3ther re2uest types&
such as F>#-F and FD:L:-:F can be used& but they may not be supported by all
bro(sers"
url
-he #RL %or the re2uest"
-he url option is the only re2uired property o% the H"a.a' con%iguration ob.ect0 all other
properties are optional"
Convenience Methods
+% you donIt need the e'tensive con%igurability o% H"a.a'& and you donIt care about handling
errors& the A.a' convenience %unctions provided by ./uery can be use%ul& terse (ays to
accomplish A.a' re2uests" -hese methods are .ust F(rappersF around the
core H"a.a' method& and simply pre-set some o% the options on theH"a.a' method"
-he convenience methods provided by ./uery are4
$.get
>er%orm a ):- re2uest to the provided #RL"
$.post
>er%orm a >3S- re2uest to the provided #RL"
$.getScript
Add a script to the page"
$.getJSON
>er%orm a ):- re2uest& and e'pect 6S3C to be returned"
+n each case& the methods tae the %ollo(ing arguments& in order4
url
-he #RL %or the re2uest" Re2uired"
data
-he data to be sent to the server" 3ptional" -his can either be an ob.ect or a 2uery
string& such as %ooYbarNba@Ybim"
Note
-his option is not valid %or H"getScript"
success callback
A callbac %unction to run i% the re2uest succeeds" 3ptional" -he %unction receives the
response data Aconverted to a 6avaScript ob.ect i% the data type (as 6S3CB& as (ell as
the te't status o% the re2uest and the ra( re2uest ob.ect"
data type
-he type o% data you e'pect bac %rom the server" 3ptional"
Note
-his option is only applicable %or methods that donIt already speci%y the data type in
their name"
Example 7.2: Using jQuery's Ajax convenience methods
11 // get plin text or ht!l
12 L.get('/users.php'4 * user<d / 123- +4 %unction(resp) *
13 console.log(resp);
1- +);
1(
1) // dd script to the pge4 then run %unction de%ined in it
15 L.get9cript('/sttic/js/!y9cript.js'4 %unction() *
16 %unctionJro!Ky9cript();
18 +);
11
11 // get ?9H0.%or!tted dt %ro! the ser$er
12 L.get?9H0('/detils.php'4 %unction(resp) *
13 L.ech(resp4 %unction(#4 $) *
1- console.log(# ' ' / ' ' $);
1( +);
1)
+);
H"%n"load
-he H"%n"load method is uni2ue among ./uery1s A.a' methods in that it is called on a
selection" -he H"%n"load method %etches *-ML %rom a #RL& and uses the returned *-ML
to populate the selected elementAsB" +n addition to providing a #RL to the method& you can
optionally provide a selector0 ./uery (ill %etch only the matching content %rom the
returned *-ML"
Example 7.3: Using $.fn.load to populate an element
1
L('One"Dontent').lod('/%oo.ht!l');
:'ample <"84 #sing H"%n"load to populate an element based on a selector
1 L('One"Dontent').lod('/%oo.ht!l O!yCi$ h1/%irst'4 %unction(ht!l) *
2 lert('Dontent updted;');
3
+);
A.a' and ,orms
./uery1s a.a' capabilities can be especially use%ul (hen dealing (ith %orms" -he ./uery
,orm >lugin is a (ell-tested tool %or adding A.a' capabilities to %orms& and you should
generally use it %or handling %orms (ith A.a' rather than trying to roll your o(n solution
%or anything remotely comple'" -hat said& there are a t(o ./uery methods you should
no( that relate to %orm processing in ./uery4 H"%n"seriali@e and H"%n"seriali@eArray"
Example 7.5: Turning form data into a query string
1
L('O!yJor!').serili2e();
:'ample <";4 Creating an array o% ob.ects containing %orm data
1 L('O!yJor!').serili2eGrry();
2
3 // cretes structure li#e this/
- =
( * n!e / '%ield1'4 $lue / 123 +4
) * n!e / '%ield2'4 $lue / 'hello "orld' +
5
>
5oring (ith 6S3C>
-he advent o% 6S3C> L essentially a consensual cross-site scripting hac L has opened
the door to po(er%ul mashups o% content" Many prominent sites provide 6S3C> services&
allo(ing you access to their content via a prede%ined A>+" A particularly great source o%
6S3C>-%ormatted data is the $ahooJ /uery Language& (hich (eIll use in the %ollo(ing
e'ample to %etch ne(s about cats"
Example 7.7: Using YQL and JSONP
11 L.jx(*
12 url / 'http///query.yhoopis.co!/$1/pu,lic/yql'4
13
1- // the n!e o% the cll,c# pr!eter4
1( // s speci%ied ,y the WQS ser$ice
1) jsonp / 'cll,c#'4
15
16 // tell jQuery "e're expecting ?9H0T
18 dtBype / 'jsonp'4
11
11 // tell WQS "ht "e "nt nd tht "e "nt ?9H0
12 dt / *
13
q / 'select title4,strct4url %ro! serch.ne"s "here
query=@ct@'4
1- %or!t / 'json'
1( +4
1)
15 // "or# "ith the response
16 success / %unction(response) *
18 console.log(response);
21 +
21
+);
./uery handles all the comple' aspects o% 6S3C> behind-the-scenes L all (e have to do is
tell ./uery the name o% the 6S3C> callbac parameter speci%ied by $/L AFcallbacF in this
caseB& and other(ise the (hole process loos and %eels lie a normal A.a' re2uest"
Ajax Events
3%ten& you1ll (ant to per%orm an operation (henever an A.a' re2uests starts or stops& such
as sho(ing or hiding a loading indicator" Rather than de%ining this behavior inside every
A.a' re2uest& you can bind A.a' events to elements .ust lie youId bind other events" ,or a
complete list o% A.a' events& visithttp4KKdocs".2uery"comKA.a'\:vents"
Example 7.8: Setting up a loading indicator using Ajax Events
1 L('OlodingPindictor')
2 .jx9trt(%unction() * L(this).sho"(); +)
3
.jx9top(%unction() * L(this).hide(); +);
:'ercises
Load External Content
3pen the %ile Ke'ercisesKinde'"html in your bro(ser" #se the %ile Ke'ercisesK.sKload".s"
$our tas is to load the content o% a blog item (hen a user clics on the title o% the item"
1. Create a target div a%ter the headline %or each blog post and store a re%erence to it on
the headline element using H"%n"data"
2. 7ind a clic event to the headline that (ill use the H"%n"load method to load the
appropriate content %rom Ke'ercisesKdataKblog"html into the target div" DonIt %orget
to prevent the de%ault action o% the clic event"
Cote that each blog headline in inde'"html includes a lin to the post" $ouIll need to
leverage the hre% o% that lin to get the proper content %rom blog"html" 3nce you have the
hre%& hereIs one (ay to process it into an +D that you can use as a selector in H"%n"load4
1 $r hre% = ',log.ht!lOpost1';
2 $r te!pGrry = hre%.split('O');
3 $r id = 'O' ' te!pGrry=1>;
Remember to mae liberal use o% console"log to mae sure youIre on the right pathJ
Load Content Using JSON
3pen the %ile Ke'ercisesKinde'"html in your bro(ser" #se the %ile Ke'ercisesK.sKspecials".s"
$our tas is to sho( the user details about the special %or a given day (hen the user selects
a day %rom the select dropdo(n"
1" Append a target div a%ter the %orm thatIs inside the Mspecials element0 this (ill be
(here you put in%ormation about the special once you receive it"
2. 7ind to the change event o% the select element0 (hen the user changes the selection&
send an A.a' re2uest to Ke'ercisesKdataKspecials".son"
3. 5hen the re2uest returns a response& use the value the user selected in the select
Ahint4 H"%n"valB to loo up in%ormation about the special in the 6S3C response"
8" Add some *-ML about the special to the target div you created"
9" ,inally& because the %orm is no( A.a'-enabled& remove the submit button %rom the
%orm"
Cote that (eIre loading the 6S3C every time the user changes their selection" *o( could
(e change the code so (e only mae the re2uest once& and then use a cached response
(hen the user changes their choice in the selectG
7ac to top
Plugins
What exactly is a plugin?
A ./uery plugin is simply a ne( method that (e use to e'tend ./ueryIs prototype ob.ect" 7y
e'tending the prototype ob.ect you enable all ./uery ob.ects to inherit any methods that
you add" As established& (henever you call ./ueryAB youIre creating a ne( ./uery ob.ect&
(ith all o% ./ueryIs methods inherited"
-he idea o% a plugin is to do something (ith a collection o% elements" $ou could consider
each method that comes (ith the ./uery core a plugin& lie %ade3ut oraddClass"
$ou can mae your o(n plugins and use them privately in your code or you can release
them into the (ild" -here are thousands o% ./uery plugins available online" -he barrier to
creating a plugin o% your o(n is so lo( that youIll (ant to do it straight a(ayJ
How to create a basic plugin
-he notation %or creating a typical plugin is as %ollo(s4
1 (%unction(L)*
2 L.%n.!y0e"Tlugin = %unction() *
3 return this.ech(%unction()*
- // do so!ething
( +);
) +;
5 +(jQuery));
DonIt let that con%use you though" -he point o% a ./uery plugin is to e'tend ./ueryIs
prototype ob.ect& and thatIs (hatIs happening on this line4
1 L.%n.!y0e"Tlugin = %unction() * //...
5e (rap this assignment in an immediately-invoed %unction4
1 (%unction(L)*
2 //...
3 +(jQuery));
-his has the e%%ect o% creating a FprivateF scope that allo(s us to e'tend ./uery using the
dollar symbol (ithout having to ris the possibility that the dollar has been over(ritten by
another library"
So our actual plugin& thus %ar& is this4
1 L.%n.!y0e"Tlugin = %unction() *
2 return this.ech(%unction()*
3 // do so!ething
- +);
( +;
-he this ey(ord (ithin the ne( plugin re%ers to the ./uery ob.ect on (hich the plugin is
being called"
1 $r so!ejQueryH,ject = L('Oso!ething');
2
3 L.%n.!y0e"Tlugin = %unction() *
- lert(this === so!ejQueryH,ject);
( +;
)
5 so!ejQueryH,ject.!y0e"Tlugin(); // lerts 'true'
$our typical ./uery ob.ect (ill contain re%erences to any number o% D3M elements& and
thatIs (hy ./uery ob.ects are o%ten re%erred to as collections"
So& to do something (ith a collection (e need to loop through it& (hich is most easily
achieved using ./ueryIs eachAB method4
1 L.%n.!y0e"Tlugin = %unction() *
2 return this.ech(%unction()*
3
- +);
( +;
./ueryIs eachAB method& lie most other ./uery methods& returns a ./uery ob.ect& thus
enabling (hat (eIve all come to no( and love as IchainingI AHA"""B"cssAB"attrAB"""B" 5e
(ouldnIt (ant to brea this convention so (e return the this ob.ect" 5ithin this loop you
can do (hatever you (ant (ith each element" *ereIs an e'ample o% a small plugin using
some o% the techni2ues (eIve discussed4
11 (%unction(L)*
12 L.%n.sho"Sin#Soction = %unction() *
13 return this.%ilter('').ech(%unction()*
1- L(this).ppend(
1( ' (' ' L(this).ttr('hre%') ' ')'
1) );
15 +);
16 +;
18 +(jQuery));
11
11 // Vsge ex!ple/
12 L('').sho"Sin#Soction();
-his handy plugin goes through all anchors in the collection and appends the hre% attribute
in bracets"
1 <;.. :e%ore plugin is clled/ ..>
2 < hre%=@pge.ht!l@>Joo</>
3
- <;.. G%ter plugin is clled/ ..>
( < hre%=@pge.ht!l@>Joo (pge.ht!l)</>
3ur plugin can be optimised though4
1 (%unction(L)*
2 L.%n.sho"Sin#Soction = %unction() *
3 return this.%ilter('').ppend(%unction()*
- return ' (' ' this.hre% ' ')';
( +);
) +;
5 +(jQuery));
5eIre using the append methodIs capability to accept a callbac& and the return value o%
that callbac (ill determine (hat is appended to each element in the collection" Cotice also
that (eIre not using the attr method to retrieve the hre% attribute& because the native D3M
A>+ gives us easy access (ith the aptly namedhre% property"
*ereIs another e'ample o% a plugin" -his one doesnIt re2uire us to loop through every
elememt (ith the eachAB method" +nstead& (eIre simply going to delegate to other ./uery
methods directly4
11 (%unction(L)*
12 L.%n.%de<nGndGddDlss = %unction(durtion4 clss0!e) *
13 return this.%de<n(durtion4 %unction()*
1- L(this).ddDlss(clss0!e);
1( +);
1) +;
15 +(jQuery));
16
18 // Vsge ex!ple/
11 L('').%de<nGndGddDlss(-114 '%inishedJding');
,inding N :valuating >lugins
>lugins e'tend the basic ./uery %unctionality& and one o% the most celebrated aspects o% the
library is its e'tensive plugin ecosystem" ,rom table sorting to %orm validation to
autocompletion """ i% there1s a need %or it& chances are good that someone has (ritten a
plugin %or it"
-he 2uality o% ./uery plugins varies (idely" Many plugins are e'tensively tested and (ell-
maintained& but others are hastily created and then ignored" More than a %e( %ail to %ollo(
best practices"
)oogle is your best initial resource %or locating plugins& though the ./uery team is (oring
on an improved plugin repository" 3nce you1ve identi%ied some options via a )oogle
search& you may (ant to consult the ./uery mailing list or the M.2uery +RC channel to get
input %rom others"
5hen looing %or a plugin to %ill a need& do your home(or" :nsure that the plugin is (ell-
documented& and loo %or the author to provide lots o% e'amples o% its use" 7e (ary o%
plugins that do %ar more than you need0 they can end up adding substantial overhead to
your page" ,or more tips on spotting a subpar plugin& readSigns o% a poorly (ritten ./uery
plugin by Remy Sharp"
3nce you choose a plugin& you1ll need to add it to your page" Do(nload the plugin& un@ip it
i% necessary& place it your application1s directory structure& then include the plugin in your
page using a script tag Aa%ter you include ./ueryB"
Writing Plugins
Sometimes you (ant to mae a piece o% %unctionality available throughout your code0 %or
e'ample& perhaps you (ant a single method you can call on a ./uery selection that
per%orms a series o% operations on the selection" +n this case& you may (ant to (rite a
plugin"
Most plugins are simply methods created in the H"%n namespace" ./uery guarantees that a
method called on a ./uery ob.ect (ill be able to access that ./uery ob.ect as this inside the
method" +n return& your plugin needs to guarantee that it returns the same ob.ect it
received& unless e'plicitly documented other(ise"
*ere is an e'ample o% a simple plugin4
Example 8.1: Creating a plugin to add and remove a class on hover
11 // de%ining the plugin
12 (%unction(L)*
13 L.%n.ho$erDlss = %unction(c) *
1- return this.ho$er(
1( %unction() * L(this).toggleDlss(c); +
1) );
15 +;
16 +)(jQuery);
18
11 // using the plugin
11
L('li').ho$erDlss('ho$er');
,or more on plugin development& read Mie AlsupIs essential post& A >lugin Development
>attern" +n it& he creates a plugin called H"%n"hilight& (hich provides support %or the
metadata plugin i% itIs present& and provides a centrali@ed method %or setting global and
instance options %or the plugin"
Example 8.2: The Mike Alsup jQuery Plugin Development Pattern
11 //
12 // crete closure
13 //
1- (%unction(L) *
1( //
1) // plugin de%inition
15 //
16 L.%n.hilight = %unction(options) *
18 de,ug(this);
11 // ,uild !in options ,e%ore ele!ent itertion
11 $r opts = L.extend(*+4 L.%n.hilight.de%ults4 options);
12 // iterte nd re%or!t ech !tched ele!ent
13 return this.ech(%unction() *
1- Lthis = L(this);
1( // ,uild ele!ent speci%ic options
1) $r o = L.!et A L.extend(*+4 opts4 Lthis.dt()) / opts;
15 // updte ele!ent styles
16 Lthis.css(*
18 ,c#groundDolor/ o.,c#ground4
21 color/ o.%oreground
21 +);
22 $r !r#up = Lthis.ht!l();
23 // cll our %or!t %unction
2- !r#up = L.%n.hilight.%or!t(!r#up);
2( Lthis.ht!l(!r#up);
2) +);
25 +;
26 //
28 // pri$te %unction %or de,ugging
31 //
31 %unction de,ug(Lo,j) *
32 i% ("indo".console 77 "indo".console.log)
33 "indo".console.log('hilight selection count/ ' ' Lo,j.si2e());
3- +;
3( //
3) // de%ine nd expose our %or!t %unction
35 //
36 L.%n.hilight.%or!t = %unction(txt) *
38 return '<strong>' ' txt ' '</strong>';
-1 +;
-1 //
-2 // plugin de%ults
-3 //
-- L.%n.hilight.de%ults = *
-( %oreground/ 'red'4
-) ,c#ground/ 'yello"'
-5 +;
-6 //
-8 // end o% closure
(1 //
(1
+)(jQuery);
5riting State%ul >lugins (ith the ./uery #+ 5idget ,actory
Note
-his section is based& (ith permission& on the blog post 7uilding State%ul ./uery >lugins by
Scott )on@ale@"
5hile most e'isting ./uery plugins are stateless L that is& (e call them on an element and
that is the e'tent o% our interaction (ith the plugin L there1s a large set o% %unctionality
that doesn1t %it into the basic plugin pattern"
+n order to %ill this gap& ./uery #+ has implemented a more advanced plugin system" -he
ne( system manages state& allo(s multiple %unctions to be e'posed via a single plugin& and
provides various e'tension points" -his system is called the (idget %actory and is e'posed
as ./uery"(idget as part o% ./uery #+ 1"=0 ho(ever& it can be used independently o% ./uery
#+"
-o demonstrate the capabilities o% the (idget %actory& (eIll build a simple progress bar
plugin"
-o start& (e1ll create a progress bar that .ust lets us set the progress once" As (e can see
belo(& this is done by calling ./uery"(idget (ith t(o parameters4 the name o% the plugin to
create and an ob.ect literal containing %unctions to support our plugin" 5hen our plugin
gets called& it (ill create a ne( plugin instance and all %unctions (ill be e'ecuted (ithin the
conte't o% that instance" -his is di%%erent %rom a standard ./uery plugin in t(o important
(ays" ,irst& the conte't is an ob.ect& not a D3M element" Second& the conte't is al(ays a
single ob.ect& never a collection"
Example 8.3: A simple, stateful plugin using the jQuery UI widget factory
1 L."idget(@n!#.progress,r@4 *
2 Pcrete/ %unction() *
3 $r progress = this.options.$lue ' @Z@;
- this.ele!ent
( .ddDlss(@progress,r@)
) .text(progress);
5 +
6
+);
-he name o% the plugin must contain a namespace0 in this case (e1ve used
the nm namespace" -here is a limitation that namespaces be e'actly one level deep L that
is& (e canIt use a namespace lie nm"%oo" 5e can also see that the (idget %actory has
provided t(o properties %or us" this"element is a ./uery ob.ect containing e'actly one
element" +% our plugin is called on a ./uery ob.ect containing multiple elements& a separate
plugin instance (ill be created %or each element& and each instance (ill have its
o(n this"element" -he second property& this"options& is a hash containing eyKvalue pairs
%or all o% our plugin1s options" -hese options can be passed to our plugin as sho(n here"
Note
+n our e'ample (e use the nm namespace" -he ui namespace is reserved %or o%%icial
./uery #+ plugins" 5hen building your o(n plugins& you should create your o(n
namespace" -his maes it clear (here the plugin came %rom and (hether it is part o% a
larger collection"
Example 8.4: Passing options to a widget
1 L(@<di$></di$>@)
2 .ppendBo( @,ody@ )
3
.progress,r(* $lue/ 21 +);
5hen (e call ./uery"(idget it e'tends ./uery by adding a method to ./uery"%n Athe same
(ay (eId create a standard pluginB" -he name o% the %unction it adds is based on the name
you pass to ./uery"(idget& (ithout the namespace0 in our case it (ill
create ./uery"%n"progressbar" -he options passed to our plugin get set
in this"options inside o% our plugin instance" As sho(n belo(& (e can speci%y de%ault values
%or any o% our options" 5hen designing your A>+& you should %igure out the most common
use case %or your plugin so that you can set appropriate de%ault values and mae all options
truly optional"
Example 8.5: Setting default options for a widget
11 L."idget(@n!#.progress,r@4 *
12 // de%ult options
13 options/ *
1- $lue/ 1
1( +4
1)
15 Pcrete/ %unction() *
16 $r progress = this.options.$lue ' @Z@;
18 this.ele!ent
11 .ddDlss( @progress,r@ )
11 .text( progress );
12 +
13
+);
Adding Methods to a 5idget
Co( that (e can initiali@e our progress bar& (e1ll add the ability to per%orm actions by
calling methods on our plugin instance" -o de%ine a plugin method& (e .ust include the
%unction in the ob.ect literal that (e pass to ./uery"(idget" 5e can also de%ine PprivateQ
methods by prepending an underscore to the %unction name"
Example 8.6: Creating widget methods
11 L."idget(@n!#.progress,r@4 *
12 options/ *
13 $lue/ 1
1- +4
1(
1) Pcrete/ %unction() *
15 $r progress = this.options.$lue ' @Z@;
16 this.ele!ent
18 .ddDlss(@progress,r@)
11 .text(progress);
11 +4
12
13 // crete pu,lic !ethod
1- $lue/ %unction($lue) *
1( // no $lue pssed4 ct s getter
1) i% ($lue === unde%ined) *
15 return this.options.$lue;
16 // $lue pssed4 ct s setter
18 + else *
21 this.options.$lue = this.Pconstrin($lue);
21 $r progress = this.options.$lue ' @Z@;
22 this.ele!ent.text(progress);
23 +
2- +4
2(
2) // crete pri$te !ethod
25 Pconstrin/ %unction($lue) *
26 i% ($lue > 111) *
28 $lue = 111;
31 +
31 i% ($lue < 1) *
32 $lue = 1;
33 +
3- return $lue;
3( +
3)
+);
-o call a method on a plugin instance& you pass the name o% the method to the ./uery
plugin" +% you are calling a method that accepts parameters& you simply pass those
parameters a%ter the method name"
Example 8.7: Calling methods on a plugin instance
11 $r ,r = L(@<di$></di$>@)
12 .ppendBo(@,ody@)
13 .progress,r(* $lue/ 21 +);
1-
1( // get the current $lue
1) lert(,r.progress,r(@$lue@));
15
16 // updte the $lue
18 ,r.progress,r(@$lue@4 (1);
11
11 // get the current $lue gin
12
lert(,r.progress,r(@$lue@));
Cote
:'ecuting methods by passing the method name to the same ./uery %unction that (as used
to initiali@e the plugin may seem odd" -his is done to prevent pollution o% the ./uery
namespace (hile maintaining the ability to chain method calls"
Working with Widget Options
3ne o% the methods that is automatically available to our plugin is the option method" -he
option method allo(s you to get and set options a%ter initiali@ation" -his method (ors
e'actly lie ./uery1s css and attr methods4 you can pass .ust a name to use it as a setter& a
name and value to use it as a single setter& or a hash o% nameKvalue pairs to set multiple
values" 5hen used as a getter& the plugin (ill return the current value o% the option that
corresponds to the name that (as passed in" 5hen used as a setter& the
plugin1s \set3ption method (ill be called %or each option that is being set" 5e can speci%y
a \set3ption method in our plugin to react to option changes"
Example 8.8: Responding when an option is set
11 L."idget(@n!#.progress,r@4 *
12 options/ *
13 $lue/ 1
1- +4
1(
1) Pcrete/ %unction() *
15 this.ele!ent.ddDlss(@progress,r@);
16 this.Pupdte();
18 +4
11
11 PsetHption/ %unction(#ey4 $lue) *
12 this.options=#ey> = $lue;
13 this.Pupdte();
1- +4
1(
1) Pupdte/ %unction() *
15 $r progress = this.options.$lue ' @Z@;
16 this.ele!ent.text(progress);
18 +
21
+);
Adding Callbacs
3ne o% the easiest (ays to mae your plugin e'tensible is to add callbacs so users can
react (hen the state o% your plugin changes" 5e can see belo( ho( to add a callbac to our
progress bar to signi%y (hen the progress has reached 100Z" -he \trigger method taes
three parameters4 the name o% the callbac& a native event ob.ect that initiated the callbac&
and a hash o% data relevant to the event" -he callbac name is the only re2uired parameter&
but the others can be very use%ul %or users (ho (ant to implement custom %unctionality on
top o% your plugin" ,or e'ample& i% (e (ere building a draggable plugin& (e could pass the
native mousemove event (hen triggering a drag callbac0 this (ould allo( users to react to
the drag based on the 'Ky coordinates provided by the event ob.ect"
Example 8.9: Providing callbacks for user extension
11 L."idget(@n!#.progress,r@4 *
12 options/ *
13 $lue/ 1
1- +4
1(
1) Pcrete/ %unction() *
15 this.ele!ent.ddDlss(@progress,r@);
16 this.Pupdte();
18 +4
11
11 PsetHption/ %unction(#ey4 $lue) *
12 this.options=#ey> = $lue;
13 this.Pupdte();
1- +4
1(
1) Pupdte/ %unction() *
15 $r progress = this.options.$lue ' @Z@;
16 this.ele!ent.text(progress);
18 i% (this.options.$lue == 111) *
21 this.Ptrigger(@co!plete@4 null4 * $lue/ 111 +);
21 +
22 +
23
+);
Callbac %unctions are essentially .ust additional options& so you can get and set them .ust
lie any other option" 5henever a callbac is e'ecuted& a corresponding event is triggered
as (ell" -he event type is determined by concatenating the plugin name and the callbac
name" -he callbac and event both receive the same t(o parameters4 an event ob.ect and a
hash o% data relevant to the event& as (e1ll see belo("
+% your plugin has %unctionality that you (ant to allo( the user to prevent& the best (ay to
support this is by creating cancelable callbacs" #sers can cancel a callbac& or its
associated event& the same (ay they cancel any native event4 by
calling event"preventDe%aultAB or using return %alse" +% the user cancels the callbac&
the \trigger method (ill return %alse so you can implement the appropriate %unctionality
(ithin your plugin"
Example 8.10: Binding to widget events
11 $r ,r = L(@<di$></di$>@)
12 .ppendBo(@,ody@)
13 .progress,r(*
1- co!plete/ %unction(e$ent4 dt) *
1( lert( @Dll,c#s re gret;@ );
1) +
15 +)
16 .,ind(@progress,rco!plete@4 %unction(e$ent4 dt) *
18
lert(@E$ents ,u,,le nd support !ny hndlers %or extre!e
%lexi,ility.@);
11 lert(@Bhe progress ,r $lue is @ ' dt.$lue);
11 +);
12
13
,r.progress,r(@option@4 @$lue@4 111);
The Widget Factory !nder the "ood
5hen you call ./uery"(idget& it creates a constructor %unction %or your plugin and sets the
ob.ect literal that you pass in as the prototype %or your plugin instances" All o% the
%unctionality that automatically gets added to your plugin comes %rom a base (idget
prototype& (hich is de%ined as ./uery"5idget"prototype" 5hen a plugin instance is created&
it is stored on the original D3M element using ./uery"data& (ith the plugin name as the
ey"
7ecause the plugin instance is directly lined to the D3M element& you can access the
plugin instance directly instead o% going through the e'posed plugin method i% you (ant"
-his (ill allo( you to call methods directly on the plugin instance instead o% passing
method names as strings and (ill also give you direct access to the plugin1s properties"
11 $r ,r = L(@<di$></di$>@)
12 .ppendBo(@,ody@)
13 .progress,r()
1- .dt(@progress,r@ );
1(
1) // cll !ethod directly on the plugin instnce
15 ,r.option(@$lue@4 (1);
16
18 // ccess properties on the plugin instnce
11 lert(,r.options.$lue);
3ne o% the biggest bene%its o% having a constructor and prototype %or a plugin is the ease o%
e'tending the plugin" 7y adding or modi%ying methods on the plugin1s prototype& (e can
modi%y the behavior o% all instances o% our plugin" ,or e'ample& i% (e (anted to add a
method to our progress bar to reset the progress to 0Z (e could add this method to the
prototype and it (ould instantly be available to be called on any plugin instance"
1 L.n!#.progress,r.prototype.reset = %unction() *
2 this.PsetHption(@$lue@4 1);
3 +;
Cleaning #p
+n some cases& it (ill mae sense to allo( users to apply and then later unapply your
plugin" $ou can accomplish this via the destroy method" 5ithin the destroymethod& you
should undo anything your plugin may have done during initiali@ation or later use"
-he destroy method is automatically called i% the element that your plugin instance is tied
to is removed %rom the D3M& so this can be used %or garbage collection as (ell" -he
de%ault destroy method removes the lin bet(een the D3M element and the plugin
instance& so it1s important to call the base %unction %rom your plugin1s destroy method"
Example 8.11: Adding a destroy method to a widget
11 L."idget( @n!#.progress,r@4 *
12 options/ *
13 $lue/ 1
1- +4
1(
1) Pcrete/ %unction() *
15 this.ele!ent.ddDlss(@progress,r@);
16 this.Pupdte();
18 +4
11
11 PsetHption/ %unction(#ey4 $lue) *
12 this.options=#ey> = $lue;
13 this.Pupdte();
1- +4
1(
1) Pupdte/ %unction() *
15 $r progress = this.options.$lue ' @Z@;
16 this.ele!ent.text(progress);
18 i% (this.options.$lue == 111 ) *
21 this.Ptrigger(@co!plete@4 null4 * $lue/ 111 +);
21 +
22 +4
23
2- destroy/ %unction() *
2( this.ele!ent
2) .re!o$eDlss(@progress,r@)
25 .text(@@);
26
28 // cll the ,se destroy %unction
31 L.Ridget.prototype.destroy.cll(this);
31 +
32
+);
Conclusion
-he (idget %actory is only one (ay o% creating state%ul plugins" -here are a %e( di%%erent
models that can be used and each have their o(n advantages and disadvantages" -he
(idget %actory solves lots o% common problems %or you and can greatly improve
productivity& it also greatly improves code reuse& maing it a great %it %or ./uery #+ as (ell
as many other state%ul plugins"
Exercises
Make a Table Sortable
,or this e'ercise& your tas is to identi%y& do(nload& and implement a table sorting plugin
on the inde'"html page" 5hen you1re done& all columns in the table on the page should be
sortable"
Write a Table-Striping Plugin
3pen the %ile Ke'ercisesKinde'"html in your bro(ser" #se the %ile Ke'ercisesK.sKstripe".s"
$our tas is to (rite a plugin called FstripeF that you can call on any table element" 5hen
the plugin is called on a table element& it should change the color o% odd ro(s in the table
body to a user-speci%ied color"
1 L('O!yB,le').stripe('Occcccc');
DonIt %orget to return the table so other methods can be chained a%ter the pluginJ
Part III. Advanced Topics
This Section is a Work in Progress
>lease visit https4KKgithub"comK.2ueryK(eb-learn-.2uery-com to contributeJ
Back to top
Performance Best Practices
-his chapter covers a number o% ./uery and 6avaScript best practices& in no particular
order" Many o% the best practices in this chapter are based on the ./uery Anti->atterns %or
>er%ormance presentation by >aul +rish"
Cache length during loops
+n a %or loop& donIt access the length property o% an array every time0 cache it be%orehand"
1 $r !ySength = !yGrry.length;
2
3 %or ($r i = 1; i < !ySength; i'') *
- // do stu%%
( +
Append ne( content outside o% a loop
-ouching the D3M comes at a cost0 i% youIre adding a lot o% elements to the D3M& do it all
at once& not one at a time"
11 // this is ,d
12 L.ech(!yGrry4 %unction(i4 ite!) *
13 $r ne"Sist<te! = '<li>' ' ite! ' '</li>';
1- L('O,llers').ppend(ne"Sist<te!);
1( +);
1)
15 // ,etter/ do this
16 $r %rg = docu!ent.creteCocu!entJrg!ent();
18
11 L.ech(!yGrry4 %unction(i4 ite!) *
11 $r ne"Sist<te! = '<li>' ' ite! ' '</li>';
12 %rg.ppendDhild(ne"Sist<te!);
13 +);
1- L('O,llers')=1>.ppendDhild(%rg);
1(
1) // or do this
15 $r !yFt!l = '';
16
18 L.ech(!yGrry4 %unction(i4 ite!) *
21 ht!l '= '<li>' ' ite! ' '</li>';
21 +);
22 L('O,llers').ht!l(!yFt!l);
]eep things DR$
DonIt repeat yoursel%0 i% youIre repeating yoursel%& youIre doing it (rong"
11 // :GC
12 i% (Le$ent%de.dt('currently') ;= 'sho"ing') *
13 Le$ent%de.stop();
1- +
1(
1) i% (Le$entho$er.dt('currently') ;= 'sho"ing') *
15 Le$entho$er.stop();
16 +
18
11 i% (Lspns.dt('currently') ;= 'sho"ing') *
11 Lspns.stop();
12 +
13
1- // YHHC;;
1( $r Lele!s = =Le$ent%de4 Le$entho$er4 Lspns>;
1) L.ech(Lele!s4 %unction(i4ele!) *
15 i% (ele!.dt('currently') ;= 'sho"ing') *
16 ele!.stop();
18 +
21 +);
7e(are anonymous %unctions
Anonymous %unctions bound every(here are a pain" -heyIre di%%icult to debug& maintain&
test& or reuse" +nstead& use an ob.ect literal to organi@e and name your handlers and
callbacs"
11 // :GC
12 L(docu!ent).redy(%unction() *
13 L('O!gic').clic#(%unction(e) *
1- L('Oyye%%ects').slideVp(%unction() *
1( // ...
1) +);
15 +);
16
18 L('Ohppiness').lod(url ' ' Ounicorns'4 %unction() *
11 // ...
11 +);
12 +);
13
1- // :EBBEI
1( $r T< = *
1) onIedy / %unction() *
15 L('O!gic').clic#(T<.cndyKtn);
16 L('Ohppiness').lod(T<.url ' ' Ounicorns'4 T<.unicornD,);
18 +4
21
21 cndyKtn / %unction(e) *
22 L('Oyye%%ects').slideVp(T<.slideD,);
23 +4
2-
2( slideD, / %unction() * ... +4
2)
25 unicornD, / %unction() * ... +
26 +;
28
31 L(docu!ent).redy(T<.onIedy);
3ptimi@e Selectors
Selector optimi@ation is less important than it used to be& as more bro(sers
implement document"2uerySelectorAllAB and the burden o% selection shi%ts %rom ./uery to
the bro(ser" *o(ever& there are still some tips to eep in mind"
ID-Based Selectors
7eginning your selector (ith an +D is al(ays best"
1 // %st
2 L('Ocontiner di$.ro,otr!');
3
- // super.%st
( L('Ocontiner').%ind('di$.ro,otr!');
-he H"%n"%ind approach is %aster because the %irst selection is handled (ithout going
through the Si@@le selector engine L +D-only selections are handled
usingdocument"get:lement7y+dAB& (hich is e'tremely %ast because it is native to the
bro(ser"
Specificity
7e speci%ic on the right-hand side o% your selector& and less speci%ic on the le%t"
1 // unopti!i2ed
2 L('di$.dt .gon2le2');
3
- // opti!i2ed
( L('.dt td.gon2le2');
#se tag"class i% possible on your right-most selector& and .ust tag or .ust "class on the le%t"
Avoid e'cessive speci%icity"
1 L('.dt t,le.ttendees td.gon2le2');
2
3 // ,etter/ drop the !iddle i% possi,le
- L('.dt td.gon2le2');
A F%latterF D3M also helps improve selector per%ormance& as the selector engine has %e(er
layers to traverse (hen looing %or an element"
Avoid the Universal Selector
Selections that speci%y or imply that a match could be %ound any(here can be very slo("
1 L('.,uttons > &'); // extre!ely expensi$e
2 L('.,uttons').children(); // !uch ,etter
3
- L('.gender /rdio'); // i!plied uni$ersl selection
( L('.gender &/rdio'); // s!e thing4 explicit no"
) L('.gender input/rdio'); // !uch ,etter
#se :vent Delegation
:vent delegation allo(s you to bind an event handler to one container element A%or
e'ample& an unordered listB instead o% multiple contained elements A%or e'ample& list
itemsB" ./uery maes this easy (ith H"%n"live and H"%n"delegate" 5here possible& you should
use H"%n"delegate instead o% H"%n"live& as it eliminates the need %or an unnecessary selection&
and its e'plicit conte't Avs" H"%n"liveIs conte't o% documentB reduces overhead by
appro'imately =0Z"
+n addition to per%ormance bene%its& event delegation also allo(s you to add ne( contained
elements to your page (ithout having to re-bind the event handlers %or them as theyIre
added"
1 // ,d (i% there re lots o% list ite!s)
2 L('li.trigger').clic#(hndlerJn);
3
- // ,etter/ e$ent delegtion "ith L.%n.li$e
( L('li.trigger').li$e('clic#'4 hndlerJn);
)
5 // ,est/ e$ent delegtion "ith L.%n.delegte
6 // llo"s you to speci%y context esily
8 L('O!ySist').delegte('li.trigger'4 'clic#'4 hndlerJn);
Detach :lements to 5or 5ith -hem
-he D3M is slo(0 you (ant to avoid manipulating it as much as possible" ./uery
introduced H"%n"detach in version 1"8 to help address this issue& allo(ing you to remove an
element %rom the D3M (hile you (or (ith it"
1 $r Lt,le = L('O!yB,le');
2 $r Lprent = Lt,le.prent();
3
- Lt,le.detch();
( // ... dd lots nd lots o% ro"s to t,le
) Lprent.ppend(t,le);
#se Stylesheets %or Changing CSS on Many
:lements
+% youIre changing the CSS o% more than 20 elements using H"%n"css& consider adding a style
tag to the page instead %or a nearly ;0Z increase in speed"
1 // %ine %or up to 21 ele!ents4 slo" %ter tht
2 L('.s"ed,erg').css('color'4 'Osd123');
3 L('<style type=@text/css@>.s"ed,erg * color / Osd123 +</style>')
- .ppendBo('hed');
#se H"data +nstead o% H"%n"data
#sing H"data on a D3M element instead o% calling H"%n"data on a ./uery selection can be up
to 10 times %aster" 7e sure you understand the di%%erence bet(een a D3M element and a
./uery selection be%ore doing this& though"
1 // regulr
2 L(ele!).dt(#ey4$lue);
3
- // 11x %ster
( L.dt(ele!4#ey4$lue);
DonIt Act on Absent :lements
./uery (onIt tell you i% youIre trying to run a (hole lot o% code on an empty selection L it
(ill proceed as though nothingIs (rong" +tIs up to you to veri%y that your selection contains
some elements"
11 // :GC/ this runs three %unctions
12 // ,e%ore it reli2es there's nothing
13 // in the selection
1- L('Onosuchthing').slideVp();
1(
1) // :etter
15 $r L!y9election = L('Onosuchthing');
16 i% (L!y9election.length) * L!y9election.slideVp(); +
18
11 // :E9B/ dd doHnce plugin
11 jQuery.%n.doHnce = %unction(%unc)*
12 this.length 77 %unc.pply(this);
13 return this;
1- +
1(
1) L('li.crtite!s').doHnce(%unction()*
15 // !#e it jx; Xo/
16 +);
-his guidance is especially applicable %or ./uery #+ (idgets& (hich have a lot o% overhead
even (hen the selection doesnIt contain elements"
Variable Definition
Eariables can be de%ined in one statement instead o% several"
1 // old 7 ,usted
2 $r test = 1;
3 $r test2 = %unction() * ... +;
- $r test3 = test2(test);
(
) // ne" hotness
5 $r test = 14
6 test2 = %unction() * ... +4
8 test3 = test2(test);
+n sel%-e'ecuting %unctions& variable de%inition can be sipped all together"
1 (%unction(%oo4 ,r) * ... +)(14 2);
Conditionals
1 // old "y
2 i% (type == '%oo' 33 type == ',r') * ... +
3
- // ,etter
( i% (/[(%oo3,r)L/.test(type)) * ... +
)
5 // o,ject literl loo#up
6 i% ((* %oo / 14 ,r / 1 +)=type>) * ... +
DonIt -reat ./uery as a 7lac 7o'
#se the source as your documentation L boomar http4KKbit"lyK.2source and re%er to it
o%ten"
7ac to top
Code Organization
Overview
5hen you move beyond adding simple enhancements to your (ebsite (ith ./uery and
start developing %ull-blo(n client-side applications& you need to consider ho( to organi@e
your code" +n this chapter& (eIll tae a loo at various code organi@ation patterns you can
use in your ./uery application and e'plore the Re2uire6S dependency management and
build system"
Key Concepts
7e%ore (e .ump into code organi@ation patterns& itIs important to understand some
concepts that are common to all good code organi@ation patterns"
$our code should be divided into units o% %unctionality L modules& services& etc"
Avoid the temptation to have all o% your code in one hugeH
AdocumentB"readyAB bloc" -his concept& loosely& is no(n as encapsulation"
DonIt repeat yoursel%" +denti%y similarities among pieces o% %unctionality& and use
inheritance techni2ues to avoid repetitive code"
Despite ./ueryIs D3M-centric nature& 6avaScript applications are not all about the
D3M" Remember that not all pieces o% %unctionality need to L or should L have a
D3M representation"
#nits o% %unctionality should be loosely coupled L a unit o% %unctionality should be
able to e'ist on its o(n& and communication bet(een units should be handled via a
messaging system such as custom events or pubKsub" Stay a(ay %rom direct
communication bet(een units o% %unctionality (henever possible"
-he concept o% loose coupling can be especially troublesome to developers maing their
%irst %oray into comple' applications& so be mind%ul o% this as youIre getting started"
Encapsulation
-he %irst step to code organi@ation is separating pieces o% your application into distinct
pieces0 sometimes& even .ust this e%%ort is su%%icient to lend
The Object Literal
An ob.ect literal is perhaps the simplest (ay to encapsulate related code" +t doesnIt o%%er
any privacy %or properties or methods& but itIs use%ul %or eliminating anonymous %unctions
%rom your code& centrali@ing con%iguration options& and easing the path to reuse and
re%actoring"
Example 10.1: An object literal
11 $r !yJeture = *
12 !yTroperty / 'hello'4
13
1- !yKethod / %unction() *
1( console.log(!yJeture.!yTroperty);
1) +4
15
16 init / %unction(settings) *
18 !yJeture.settings = settings;
11 +4
11
12 red9ettings / %unction() *
13 console.log(!yJeture.settings);
1- +
1( +;
1)
15 !yJeture.!yTroperty; // 'hello'
16 !yJeture.!yKethod(); // logs 'hello'
18 !yJeture.init(* %oo / ',r' +);
21
!yJeture.red9ettings(); // logs * %oo / ',r' +
-he ob.ect literal above is simply an ob.ect assigned to a variable" -he ob.ect has one
property and several methods" All o% the properties and methods are public& so any part o%
your application can see the properties and call methods on the ob.ect" 5hile there is an
init method& thereIs nothing re2uiring that it be called be%ore the ob.ect is %unctional"
*o( (ould (e apply this pattern to ./uery codeG LetIs say that (e had this code (ritten in
the traditional ./uery style4
11 // clic#ing on list ite! lods so!e content
12 // using the list ite!'s <C nd hides content
13 // in si,ling list ite!s
1- L(docu!ent).redy(%unction() *
1( L('O!yJeture li')
1) .ppend('<di$/>')
15 .clic#(%unction() *
16 $r Lthis = L(this);
18 $r Ldi$ = Lthis.%ind('di$');
11 Ldi$.lod('%oo.phpAite!=' '
11 Lthis.ttr('id')4
12 %unction() *
13 Ldi$.sho"();
1- Lthis.si,lings()
1( .%ind('di$').hide();
1) +
15 );
16 +);
18 +);
+% this (ere the e'tent o% our application& leaving it as-is (ould be %ine" 3n the other hand&
i% this (as a piece o% a larger application& (eId do (ell to eep this %unctionality separate
%rom unrelated %unctionality" 5e might also (ant to move the #RL out o% the code and into
a con%iguration area" ,inally& (e might (ant to brea up the chain to mae it easier to
modi%y pieces o% the %unctionality later"
Example 10.2: Using an object literal for a jQuery feature
11 $r !yJeture = *
12 init / %unction(settings) *
13 !yJeture.con%ig = *
1- Lite!s / L('O!yJeture li')4
1( Lcontiner / L('<di$ clss=@continer@></di$>')4
1) url:se / '/%oo.phpAite!='
15 +;
16
18 // llo" o$erriding the de%ult con%ig
11 L.extend(!yJeture.con%ig4 settings);
11
12 !yJeture.setup();
13 +4
1-
1( setup / %unction() *
1) !yJeture.con%ig.Lite!s
15 .ech(!yJeture.creteDontiner)
16 .clic#(!yJeture.sho"<te!);
18 +4
21
21 creteDontiner / %unction() *
22 $r Li = L(this)4
23 Lc = !yJeture.con%ig.Lcontiner.clone()
2- .ppendBo(Li);
2(
2) Li.dt('continer'4 Lc);
25 +4
26
28 ,uildVrl / %unction() *
31 return !yJeture.con%ig.url:se '
31 !yJeture.Lcurrent<te!.ttr('id');
32 +4
33
3- sho"<te! / %unction() *
3( $r !yJeture.Lcurrent<te! = L(this);
3) !yJeture.getDontent(!yJeture.sho"Dontent);
35 +4
36
38 getDontent / %unction(cll,c#) *
-1 $r url = !yJeture.,uildVrl();
-1 !yJeture.Lcurrent<te!
-2 .dt('continer').lod(url4 cll,c#);
-3 +4
--
-( sho"Dontent / %unction() *
-) !yJeture.Lcurrent<te!
-5 .dt('continer').sho"();
-6 !yJeture.hideDontent();
-8 +4
(1
(1 hideDontent / %unction() *
(2 !yJeture.Lcurrent<te!.si,lings()
(3 .ech(%unction() *
(- L(this).dt('continer').hide();
(( +);
() +
(5 +;
(6
(8
L(docu!ent).redy(!yJeture.init);
-he %irst thing youIll notice is that this approach is obviously %ar longer than the original L
again& i% this (ere the e'tent o% our application& using an ob.ect literal (ould liely be
overill" Assuming itIs not the e'tent o% our application& though& (eIve gained several
things4
5eIve broen our %eature up into tiny methods" +n the %uture& i% (e (ant to change
ho( content is sho(n& itIs clear (here to change it" +n the original code& this step is
much harder to locate"
5eIve eliminated the use o% anonymous %unctions"
5eIve moved con%iguration options out o% the body o% the code and put them in a
central location"
5eIve eliminated the constraints o% the chain& maing the code easier to re%actor&
remi'& and rearrange"
,or non-trivial %eatures& ob.ect literals are a clear improvement over a long stretch o% code
stu%%ed in a HAdocumentB"readyAB bloc& as they get us thining about the pieces o% our
%unctionality" *o(ever& they arenIt a (hole lot more advanced than simply having a bunch
o% %unction declarations inside o% that HAdocumentB"readyAB bloc"
The Module Pattern
-he module pattern overcomes some o% the limitations o% the ob.ect literal& o%%ering privacy
%or variables and %unctions (hile e'posing a public A>+ i% desired"
Example 10.3: The module pattern
11 $r %eture =(%unction() *
12
13 // pri$te $ri,les nd %unctions
1- $r pri$teBhing = 'secret'4
1( pu,licBhing = 'not secret'4
1)
15 chngeTri$teBhing = %unction() *
16 pri$teBhing = 'super secret';
18 +4
11
11 syTri$teBhing = %unction() *
12 console.log(pri$teBhing);
13 chngeTri$teBhing();
1- +;
1(
1) // pu,lic GT<
15 return *
16 pu,licBhing / pu,licBhing4
18 syTri$teBhing / syTri$teBhing
21 +
21
22 +)();
23
2- %eture.pu,licBhing; // 'not secret'
2(
2) %eture.syTri$teBhing();
25 // logs 'secret' nd chnges the $lue
26
// o% pri$teBhing
+n the e'ample above& (e sel%-e'ecute an anonymous %unction that returns an ob.ect"
+nside o% the %unction& (e de%ine some variables" 7ecause the variables are de%ined inside o%
the %unction& (e donIt have access to them outside o% the %unction unless (e put them in
the return ob.ect" -his means that no code outside o% the %unction has access to
the private-hing variable or to the change>rivate-hing %unction"
*o(ever& say>rivate-hing does have access to private-hing andchange>rivate-hing&
because both (ere de%ined in the same scope as say>rivate-hing"
-his pattern is po(er%ul because& as you can gather %rom the variable names& it can give
you private variables and %unctions (hile e'posing a limited A>+ consisting o% the returned
ob.ectIs properties and methods"
7elo( is a revised version o% the previous e'ample& sho(ing ho( (e could create the same
%eature using the module pattern (hile only e'posing one public method o% the
module& sho(+tem7y+nde'AB"
Example 10.4: Using the module pattern for a jQuery feature
11 L(docu!ent).redy(%unction() *
12 $r %eture = (%unction() *
13
1- $r Lite!s = L('O!yJeture li')4
1( Lcontiner = L('<di$ clss=@continer@></di$>')4
1) Lcurrent<te!4
15
16 url:se = '/%oo.phpAite!='4
18
11 creteDontiner = %unction() *
11 $r Li = L(this)4
12 Lc = Lcontiner.clone().ppendBo(Li);
13
1- Li.dt('continer'4 Lc);
1( +4
1)
15 ,uildVrl = %unction() *
16 return url:se ' Lcurrent<te!.ttr('id');
18 +4
21
21 sho"<te! = %unction() *
22 $r Lcurrent<te! = L(this);
23 getDontent(sho"Dontent);
2- +4
2(
2) sho"<te!:y<ndex = %unction(idx) *
25 L.proxy(sho"<te!4 Lite!s.get(idx));
26 +4
28
31 getDontent = %unction(cll,c#) *
31
Lcurrent<te!.dt('continer').lod(,uildVrl()4
cll,c#);
32 +4
33
3- sho"Dontent = %unction() *
3( Lcurrent<te!.dt('continer').sho"();
3) hideDontent();
35 +4
36
38 hideDontent = %unction() *
-1 Lcurrent<te!.si,lings()
-1 .ech(%unction() *
-2 L(this).dt('continer').hide();
-3 +);
-- +;
-(
-) Lite!s
-5 .ech(creteDontiner)
-6 .clic#(sho"<te!);
-8
(1 return * sho"<te!:y<ndex / sho"<te!:y<ndex +;
(1 +)();
(2
(3 %eture.sho"<te!:y<ndex(1);
(-
+);
Managing Dependencies
Note
-his section is based heavily on the e'cellent Re2uire6S documentation
at http4KKre2uire.s"orgKdocsK.2uery"html& and is used (ith the permission o% Re2uire6S
author 6ames 7ure"
5hen a pro.ect reaches a certain si@e& managing the script modules %or a pro.ect starts to
get tricy" $ou need to be sure to se2uence the scripts in the right order& and you need to
start seriously thining about combining scripts together into a bundle %or deployment& so
that only one or a very small number o% re2uests are made to load the scripts" $ou may also
(ant to load code on the %ly& a%ter page load"
Re2uire6S& a dependency management tool by 6ames 7ure& can help you manage the
script modules& load them in the right order& and mae it easy to combine the scripts later
via the Re2uire6S optimi@ation tool (ithout needing to change your marup" +t also gives
you an easy (ay to load scripts a%ter the page has loaded& allo(ing you to spread out the
do(nload si@e over time"
Re2uire6S has a module system that lets you de%ine (ell-scoped modules& but you do not
have to %ollo( that system to get the bene%its o% dependency management and build-time
optimi@ations" 3ver time& i% you start to create more modular code that needs to be reused
in a %e( places& the module %ormat %or Re2uire6S maes it easy to (rite encapsulated code
that can be loaded on the %ly" +t can gro( (ith you& particularly i% you (ant to incorporate
internationali@ation Ai1=nB string bundles& to locali@e your pro.ect %or di%%erent languages&
or load some *-ML strings and mae sure those strings are available be%ore e'ecuting
code& or even use 6S3C> services as dependencies"
Getting RequireJS
-he easiest (ay to use Re2uire6S (ith ./uery is to do(nload a build o% ./uery that has
Re2uire6S built in" -his build e'cludes portions o% Re2uire6S that duplicate ./uery
%unctionality" $ou may also %ind it use%ul to do(nload a sample ./uery pro.ect that uses
Re2uire6S"
Using RequireJS with jQuery
#sing Re2uire6S in your page is simple4 .ust include the ./uery that has Re2uire6S built in&
then re2uire your application %iles" -he %ollo(ing e'ample assumes that the ./uery build&
and your other scripts& are all in a scriptsK directory"
Example 10.5: Using RequireJS: A simple example
11 <;CHDBWTE ht!l>
12 <ht!l>
13 <hed>
1- <title>jQuery'Iequire?9 9!ple Tge</title>
1( <script src=@scripts/require.jquery.js@></script>
1) <script>require(=@pp@>);</script>
15 </hed>
16 <,ody>
18 <h1>jQuery'Iequire?9 9!ple Tge</h1>
11 </,ody>
</ht!l>
-he call to re2uireARFappFSB tells Re2uire6S to load the scriptsKapp".s %ile" Re2uire6S (ill
load any dependency that is passed to re2uireAB (ithout a ".se'tension %rom the same
directory as re2uire-.2uery".s& though this can be con%igured to behave di%%erently" +% you
%eel more com%ortable speci%ying the (hole path& you can also do the %ollo(ing4
1 <script>require(=@scripts/pp.js@>);</script>
5hat is in app".sG Another call to re2uire".s to load all the scripts you need and any init
(or you (ant to do %or the page" -his e'ample app".s script loads t(o
plugins& .2uery"alpha".s and .2uery"beta".s Anot the names o% real plugins& .ust an e'ampleB"
-he plugins should be in the same directory as re2uire-.2uery".s4
Example 10.6: A simple JavaScript file with dependencies
1 require(=@jquery.lph@4 @jquery.,et@>4 %unction() *
2 //the jquery.lph.js nd jquery.,et.js plugins h$e ,een loded.
3 L(%unction() *
- L(',ody').lph().,et();
( +);
)
+);
Creating Reusable Modules (ith Re2uire6S
Re2uire6S maes it easy to de%ine reusable modules via re2uire"de%AB" A Re2uire6S module
can have dependencies that can be used to de%ine a module& and a Re2uire6S module can
return a value L an ob.ect& a %unction& (hatever L that can then be consumed by yet other
modules"
+% your module does not have any dependencies& then .ust speci%y the name o% the module
as the %irst argument to re2uire"de%AB" -he second argument is .ust an ob.ect literal that
de%ines the moduleIs properties" ,or e'ample4
Example 10.7: Defining a RequireJS module that has no dependencies
1 require.de%(@!y/si!pleshirt@4
2 *
3 color/ @,lc#@4
- si2e/ @unisi2e@
( +
-his e'ample (ould be stored in a myKsimpleshirt".s %ile"
+% your module has dependencies& you can speci%y the dependencies as the second
argument to re2uire"de%AB Aas an arrayB and then pass a %unction as the third argument" -he
%unction (ill be called to de%ine the module once all dependencies have loaded" -he
%unction receives the values returned by the dependencies as its arguments Ain the same
order they (ere re2uired in the arrayB& and the %unction should return an ob.ect that
de%ines the module"
Example 10.8: Defining a RequireJS module with dependencies
11 require.de%(@!y/shirt@4
12 =@!y/crt@4 @!y/in$entory@>4
13 %unction(crt4 in$entory) *
1- //return n o,ject to de%ine the @!y/shirt@ !odule.
1( return *
1) color/ @,lue@4
15 si2e/ @lrge@
16 ddBoDrt/ %unction() *
18 in$entory.decre!ent(this);
11 crt.dd(this);
11 +
12 +
13 +
1-
);
+n this e'ample& a myKshirt module is created" +t depends on myKcart and myKinventory"
3n dis& the %iles are structured lie this4
1 !y/crt.js
2 !y/in$entory.js
3 !y/shirt.js
-he %unction that de%ines myKshirt is not called until
the myKcart and myKinventory modules have been loaded& and the %unction receives the
modules as the cartand inventory arguments" -he order o% the %unction arguments must
match the order in (hich the dependencies (ere re2uired in the dependencies array" -he
ob.ect returned by the %unction call de%ines the myKshirt module" 7e de%ining modules in
this (ay& myKshirt does not e'ist as a global ob.ect" Modules that de%ine globals are
e'plicitly discouraged& so multiple versions o% a module can e'ist in a page at a time"
Modules do not have to return ob.ects0 any valid return value %rom a %unction is allo(ed"
Example 10.9: Defining a RequireJS module that returns a function
11 require.de%(@!y/title@4
12 =@!y/dependency1@4 @!y/dependency2@>4
13 %unction(dep14 dep2) *
1- //return %unction to de%ine @!y/title@. <t gets or sets
1( //the "indo" title.
1) return %unction(title) *
15 return title A ("indo".title = title) / "indo".title;
16 +
18 +
11
);
3nly one module should be re2uired per 6avaScript %ile"
Optimizing Your Code: The RequireJS Build Tool
3nce you incorporate Re2uire6S %or dependency management& your page is set up to be
optimi@ed very easily" Do(nload the Re2uire6S source and place it any(here you lie&
pre%errably some(here outside your (eb development area" ,or the purposes o% this
e'ample& the Re2uire6S source is placed as a sibling to the (ebapp directory& (hich
contains the *-ML page and the scripts directory (ith all the scripts" Complete directory
structure4
1 requirejs/ (used %or the ,uild tools)
2 "e,pp/pp.ht!l
3 "e,pp/scripts/pp.js
- "e,pp/scripts/require.jquery.js
( "e,pp/scripts/jquery.lph.js
) "e,pp/scripts/jquery.,et.js
-hen& in the scripts directory that has re2uire-.2uery".s and app".s& create a %ile called
app"build".s (ith the %ollo(ing contents4
A RequireJS build configuration file
11 *
12 ppCir/ @../@4
13 ,seVrl/ @scripts/@4
1- dir/ @../../"e,pp.,uild@4
1( //Do!!ent out the opti!i2e line i% you "nt
1) //the code !ini%ied ,y Dlosure Do!piler using
15 //the @si!ple@ opti!i2tions !ode
16 opti!i2e/ @none@4
18
11 !odules/ =
11 *
12 n!e/ @pp@
13 +
1- >
1(
+
-o use the build tool& you need 6ava ; installed" Closure Compiler is used %or the
6avaScript mini%ication step Ai% optimi@e4 FnoneF is commented outB& and it re2uires 6ava ;"
-o start the build& go to the (ebappKscripts directory& e'ecute the %ollo(ing command4
1 O non."indo"s syste!s
2 ../../requirejs/,uild/,uild.sh pp.,uild.js
3
- O "indo"s syste!s
( ..X..XrequirejsX,uildX,uild.,t pp.,uild.js
Co(& in the (ebapp-build directory& app".s (ill have
the app".s contents& .2uery"alpha".s and .2uery"beta".s inlined" +% you then load
the app"html %ile in the(ebapp-build directory& you should not see any net(or re2uests
%or .2uery"alpha".s and .2uery"beta".s"
Exercises
Create a Portlet Module
3pen the %ile Ke'ercisesKportlets"html in your bro(ser" #se the
%ile Ke'ercisesK.sKportlets".s" $our tas is to create a portlet creation %unction that uses the
module pattern& such that the %ollo(ing code (ill (or4
1 $r !yTortlet = Tortlet(*
2 title / 'Durry'4
3 source / 'dt/ht!l/curry.ht!l'4
- initil9tte / 'open' // or 'closed'
( +);
)
5 !yTortlet.Lele!ent.ppendBo(',ody');
:ach portlet should be a div (ith a title& a content area& a button to openKclose the portlet&
a button to remove the portlet& and a button to re%resh the portlet" -he portlet returned by
the >ortlet %unction should have the %ollo(ing public A>+4
1 !yTortlet.open(); // %orce open stte
2 !yTortlet.close(); // %orce close stte
3 !yTortlet.toggle(); // toggle open/close stte
- !yTortlet.re%resh(); // re%resh the content
( !yTortlet.destroy(); // re!o$e the portlet %ro! the pge
) !yTortlet.set9ource('dt/ht!l/onions.ht!l');
5 // chnge the source
Back to top
Custom Events
Introducing Custom Events
5e1re all %amiliar (ith the basic events L clic& mouseover& %ocus& blur& submit& etc" L that
(e can latch on to as a user interacts (ith the bro(ser" Custom events open up a (hole
ne( (orld o% event-driven programming" +n this chapter& (e1ll use ./uery1s custom events
system to mae a simple -(itter search application"
+t can be di%%icult at %irst to understand (hy youId (ant to use custom events& (hen the
built-in events seem to suit your needs .ust %ine" +t turns out that custom events o%%er a
(hole ne( (ay o% thining about event-driven 6avaScript" +nstead o% %ocusing on the
element that triggers an action& custom events put the spotlight on the element being acted
upon" -his brings a bevy o% bene%its& including4
7ehaviors o% the target element can easily be triggered by di%%erent elements using
the same code"
7ehaviors can be triggered across multiple& similar& target elements at once"
7ehaviors are more clearly associated (ith the target element in code& maing code
easier to read and maintain"
5hy should you careG An e'ample is probably the best (ay to e'plain" Suppose you have a
lightbulb in a room in a house" -he lightbulb is currently turned on& and it1s controlled by
t(o three-(ay s(itches and a clapper4
1 <di$ clss=@roo!@ id=@#itchen@>
2 <di$ clss=@light,ul, on@></di$>
3 <di$ clss=@s"itch@></di$>
- <di$ clss=@s"itch@></di$>
( <di$ clss=@clpper@></di$>
) </di$>
-riggering the clapper or either o% the s(itches (ill change the state o% the lightbulb" -he
s(itches and the clapper don1t care (hat state the lightbulb is in0 they .ust (ant to change
the state"
5ithout custom events& you might (rite some code lie this4
1 L('.s"itch4 .clpper').clic#(%unction() *
2 $r Llight = L(this).prent().%ind('.light,ul,');
3 i% (Llight.hsDlss('on')) *
- Llight.re!o$eDlss('on').ddDlss('o%%');
( + else *
) Llight.re!o$eDlss('o%%').ddDlss('on');
5 +
6 +);
5ith custom events& your code might loo more lie this4
11 L('.light,ul,').,ind('chnge9tte'4 %unction(e) *
12 $r Llight = L(this);
13 i% (Llight.hsDlss('on')) *
1- Llight.re!o$eDlss('on').ddDlss('o%%');
1( + else *
1) Llight.re!o$eDlss('o%%').ddDlss('on');
15 +
16 +);
18
11 L('.s"itch4 .clpper').clic#(%unction() *
11 L(this).prent().%ind('.light,ul,').trigger('chnge9tte');
12 +);
-his last bit o% code is not that e'citing& but something important has happened4 (e1ve
moved the behavior o% the lightbulb to the lightbulb& and a(ay %rom the s(itches and the
clapper"
Let1s mae our e'ample a little more interesting" 5e1ll add another room to our house&
along (ith a master s(itch& as sho(n here4
11 <di$ clss=@roo!@ id=@#itchen@>
12 <di$ clss=@light,ul, on@></di$>
13 <di$ clss=@s"itch@></di$>
1- <di$ clss=@s"itch@></di$>
1( <di$ clss=@clpper@></di$>
1) </di$>
15 <di$ clss=@roo!@ id=@,edroo!@>
16 <di$ clss=@light,ul, on@></di$>
18 <di$ clss=@s"itch@></di$>
11 <di$ clss=@s"itch@></di$>
11 <di$ clss=@clpper@></di$>
12 </di$>
13 <di$ id=@!sterPs"itch@></di$>
+% there are any lights on in the house& (e (ant the master s(itch to turn all the lights o%%0
other(ise& (e (ant it to turn all lights on" -o accomplish this& (e1ll add t(o more custom
events to the lightbulbs4 turn3n and turn3%%" 5e1ll mae use o% them in
the changeState custom event& and use some logic to decide (hich one the master s(itch
should trigger4
11 L('.light,ul,')
12 .,ind('chnge9tte'4 %unction(e) *
13 $r Llight = L(this);
1- i% (Llight.hsDlss('on')) *
1( Llight.trigger('turnH%%');
1) + else *
15 Llight.trigger('turnHn');
16 +
18 +)
11 .,ind('turnHn'4 %unction(e) *
11 L(this).re!o$eDlss('o%%').ddDlss('on');
12 +)
13 .,ind('turnH%%'4 %unction(e) *
1- L(this).re!o$eDlss('o%%').ddDlss('on');
1( +);
1)
15 L('.s"itch4 .clpper').clic#(%unction() *
16 L(this).prent().%ind('.light,ul,').trigger('chnge9tte');
18 +);
21
21 L('O!sterPs"itch').clic#(%unction() *
22 i% (L('.light,ul,.on').length) *
23 L('.light,ul,').trigger('turnH%%');
2- + else *
2( L('.light,ul,').trigger('turnHn');
2) +
25 +);
Cote ho( the behavior o% the master s(itch is attached to the master s(itch0 the behavior
o% a lightbulb belongs to the lightbulbs"
Note
+% you1re accustomed to ob.ect-oriented programming& you may %ind it use%ul to thin o%
custom events as methods o% ob.ects" Loosely speaing& the ob.ect to (hich the method
belongs is created via the ./uery selector" 7inding the changeState custom event to all H
A^"light1B elements is ain to having a class calledLight (ith a method o% changeState& and
then instantiating ne( Light ob.ects %or each element (ith a classname o% light"
#eca$ $.fn.bind and $.fn.trigger
+n the (orld o% custom events& there are t(o important ./uery
methods4 H"%n"bind and H"%n"trigger" +n the :vents chapter& (e sa( ho( to use these
methods %or (oring (ith user events0 %or this chapter& itIs important to remember t(o
things4
-he H"%n"bind method taes an event type and an event handling %unction as
arguments" 3ptionally& it can also receive event-related data as its second argument&
pushing the event handling %unction to the third argument" Any data that is passed
(ill be available to the event handling %unction in the dataproperty o% the event
ob.ect" -he event handling %unction al(ays receives the event ob.ect as its %irst
argument"
-he H"%n"trigger method taes an event type as its argument" 3ptionally& it can also
tae an array o% values" -hese values (ill be passed to the event handling %unction as
arguments a%ter the event ob.ect"
*ere is an e'ample o% the usage o% H"%n"bind and H"%n"trigger that uses custom data in both
cases4
1
L(docu!ent).,ind('!yDusto!E$ent'4 * %oo / ',r' +4 %unction(e4 rg14
rg2) *
2 console.log(e.dt.%oo); // ',r'
3 console.log(rg1); // ',i!'
- console.log(rg2); // ',2'
( +);
)
5 L(docu!ent).trigger('!yDusto!E$ent'4 = ',i!'4 ',2' >);
A Sample Application
-o demonstrate the po(er o% custom events& (e1re going to create a simple tool %or
searching -(itter" -he tool (ill o%%er several (ays %or a user to add search terms to the
display4 by entering a search term in a te't bo'& by entering multiple search terms in the
#RL& and by 2uerying -(itter %or trending terms"
-he results %or each term (ill be sho(n in a results container0 these containers (ill be able
to be e'panded& collapsed& re%reshed& and removed& either individually or all at once"
5hen (e1re done& it (ill loo lie this4
Figure %%.%. &ur finished a$$lication
The Setup
5e1ll start (ith some basic *-ML4
11 <h1>B"itter 9erch</h1>
12 <input type=@,utton@ id=@getPtrends@
13 $lue=@Sod Brending Ber!s@ />
1-
1( <%or!>
1) <input type=@text@ clss=@inputPtext@
15 id=@serchPter!@ />
16 <input type=@su,!it@ clss=@inputPsu,!it@
18 $lue=@Gdd 9erch Ber!@ />
11 </%or!>
11
12 <di$ id=@t"itter@>
13 <di$ clss=@te!plte results@>
1- <h2>9erch Iesults %or
1( <spn clss=@serchPter!@></spn></h2>
1) </di$>
15 </di$>
-his gives us a container AMt(itterB %or our (idget& a template %or our results containers
Ahidden via CSSB& and a simple %orm (here users can input a search term" A,or the sae o%
simplicity& (e1re going to assume that our application is 6avaScript-only and that our users
(ill al(ays have CSS"B
-here are t(o types o% ob.ects (e1ll (ant to act on4 the results containers& and the -(itter
container"
-he results containers are the heart o% the application" 5e1ll create a plugin that (ill
prepare each results container once it1s added to the -(itter container" Among other
things& it (ill bind the custom events %or each container and add the action buttons at the
top right o% each container" :ach results container (ill have the %ollo(ing custom events4
refresh
Mar the container as being in the Pre%reshingQ state& and %ire the re2uest to %etch the
data %or the search term"
populate
Receive the returned 6S3C data and use it to populate the container"
remove
Remove the container %rom the page a%ter the user veri%ies the re2uest to do so"
Eeri%ication can be bypassed by passing true as the second argument to the event
handler" -he remove event also removes the term associated (ith the results
container %rom the global ob.ect containing the search terms"
collapse
Add a class o% collapsed to the container& (hich (ill hide the results via CSS" +t (ill
also turn the container1s PCollapseQ button into an P:'pandQ button"
expand
Remove the collapsed class %rom the container" +t (ill also turn the container1s
P:'pandQ button into a PCollapseQ button"
-he plugin is also responsible %or adding the action buttons to the container" +t binds a
clic event to each action1s list item& and uses the list item1s class to determine (hich
custom event (ill be triggered on the corresponding results container"
111 L.%n.t"itterIesult = %unction(settings) *
112 return this.ech(%unction() *
113 $r Lresults = L(this)4
11- Lctions = L.%n.t"itterIesult.ctions =
11( L.%n.t"itterIesult.ctions 33
11) L.%n.t"itterIesult.creteGctions()4
115 L = Lctions.clone().prependBo(Lresults)4
116 ter! = settings.ter!;
118
111 Lresults.%ind('spn.serchPter!').text(ter!);
111
112 L.ech(
113
='re%resh'4 'populte'4 're!o$e'4 'collpse'4 'expnd'>
4
11- %unction(i4 e$) *
11( Lresults.,ind(
11) e$4
115 * ter! / ter! +4
116 L.%n.t"itterIesult.e$ents=e$>
118 );
121 +
121 );
122
123 // use the clss o% ech ction to %igure out
12- // "hich e$ent it "ill trigger on the results pnel
12( L.%ind('li').clic#(%unction() *
12) // pss the li tht "s clic#ed to the %unction
125 // so it cn ,e !nipulted i% needed
126 Lresults.trigger(L(this).ttr('clss')4 = L(this) >);
128 +);
131 +);
131 +;
132
133 L.%n.t"itterIesult.creteGctions = %unction() *
13- return L('<ul clss=@ctions@ />').ppend(
13( '<li clss=@re%resh@>Ie%resh</li>' '
13) '<li clss=@re!o$e@>Ie!o$e</li>' '
135 '<li clss=@collpse@>Dollpse</li>'
136 );
138 +;
1-1
1-1 L.%n.t"itterIesult.e$ents = *
1-2 re%resh / %unction(e) *
1-3 // indicte tht the results re re%reshing
1-- $r Lthis = L(this).ddDlss('re%reshing');
1-(
1-) Lthis.%ind('p.t"eet').re!o$e();
1-5 Lresults.ppend('<p clss=@loding@>Soding ...</p>');
1-6
1-8 // get the t"itter dt using jsonp
1(1 L.get?9H0(
1(1 'http///serch.t"itter.co!/serch.jsonAq=' '
1(2 escpe(e.dt.ter!) ' '7rpp=(7cll,c#=A'4
1(3 %unction(json) *
1(- Lthis.trigger('populte'4 = json >);
1(( +
1() );
1(5 +4
1(6
1(8 populte / %unction(e4 json) *
1)1 $r results = json.results;
1)1 $r Lthis = L(this);
1)2
1)3 Lthis.%ind('p.loding').re!o$e();
1)-
1)( L.ech(results4 %unction(i4result) *
1)) $r t"eet = '<p clss=@t"eet@>' '
1)5 '< hre%=@http///t"itter.co!/' '
1)6 result.%ro!Puser '
1)8 '@>' '
151 result.%ro!Puser '
151 '</>/ ' '
152 result.text '
153 ' <spn clss=@dte@>' '
15- result.cretedPt '
15( '</spn>' '
15) '</p>';
155 Lthis.ppend(t"eet);
156 +);
158
161 // indicte tht the results
161 // re done re%reshing
162 Lthis.re!o$eDlss('re%reshing');
163 +4
16-
16( re!o$e / %unction(e4 %orce) *
16) i% (
165 ;%orce 77
166 ;con%ir!('Ie!o$e pnel %or ter! ' ' e.dt.ter! ' 'A')
168 ) *
181 return;
181 +
182 L(this).re!o$e();
183
18- // indicte tht "e no longer
18( // h$e pnel %or the ter!
18) serchPter!s=e.dt.ter!> = 1;
185 +4
186
188 collpse / %unction(e) *
111 L(this).%ind('li.collpse').re!o$eDlss('collpse')
111 .ddDlss('expnd').text('Expnd');
112
113 L(this).ddDlss('collpsed');
11- +4
11(
11) expnd / %unction(e) *
115 L(this).%ind('li.expnd').re!o$eDlss('expnd')
116 .ddDlss('collpse').text('Dollpse');
118
111 L(this).re!o$eDlss('collpsed');
111 +
112 +;
-he -(itter container itsel% (ill have .ust t(o custom events4
getResults
Receives a search term and checs to determine (hether there1s already a results
container %or the term0 i% not& adds a results container using the results template& set
up the results container using the H"%n"t(itterResult plugin discussed above& and then
triggers the re%resh event on the results container in order to actually load the results"
,inally& it (ill store the search term so the application no(s not to re-%etch the term"
getTrends
/ueries -(itter %or the top 10 trending terms& then iterates over them and triggers
the getResults event %or each o% them& thereby adding a results container %or each
term"
*ereIs ho( the -(itter container bindings loo4
11 L('Ot"itter')
12 .,ind('getIesults'4 %unction(e4 ter!) *
13 // !#e sure "e don't h$e ,ox %or this ter! lredy
1- i% (;serchPter!s=ter!>) *
1( $r Lthis = L(this);
1) $r Lte!plte = Lthis.%ind('di$.te!plte');
15
16 // !#e copy o% the te!plte di$
18 // nd insert it s the %irst results ,ox
11 Lresults = Lte!plte.clone().
11 re!o$eDlss('te!plte').
12 insert:e%ore(Lthis.%ind('di$/%irst')).
13 t"itterIesult(*
1- 'ter!' / ter!
1( +);
1)
15 // lod the content using the @re%resh@
16 // custo! e$ent tht "e ,ound to the results continer
18 Lresults.trigger('re%resh');
21 serchPter!s=ter!> = 1;
21 +
22 +)
23 .,ind('getBrends'4 %unction(e) *
2- $r Lthis = L(this);
2(
L.get?9H0('http///serch.t"itter.co!/trends.jsonA
cll,c#=A'4 %unction(json) *
2) $r trends = json.trends;
25 L.ech(trends4 %unction(i4 trend) *
26 Lthis.trigger('getIesults'4 = trend.n!e >);
28 +);
31 +);
31 +);
So %ar& (e1ve (ritten a lot o% code that does appro'imately nothing& but that1s 3]" 7y
speci%ying all the behaviors that (e (ant our core ob.ects to have& (e1ve created a solid
%rame(or %or rapidly building out the inter%ace"
Let1s start by hooing up our te't input and the PLoad -rending -ermsQ button" ,or the
te't input& (e1ll capture the term that (as entered in the input and pass it as (e trigger the
-(itter container1s getResults event" Clicing the PLoad -rending -ermsQ (ill trigger the
-(itter container1s get-rends event4
1 L('%or!').su,!it(%unction(e) *
2 e.pre$entCe%ult();
3 $r ter! = L('OserchPter!').$l();
- L('Ot"itter').trigger('getIesults'4 = ter! >);
( +);
)
5 L('OgetPtrends').clic#(%unction() *
6 L('Ot"itter').trigger('getBrends');
8 +);
7y adding a %e( buttons (ith the appropriate +Ds& (e can mae it possible to remove&
collapse& e'pand& and re%resh all results containers at once& as sho(n belo(" ,or the
remove button& note ho( (e1re passing a value o% true to the event handler as its second
argument& telling the event handler that (e don1t (ant to veri%y the removal o% individual
containers"
1 L.ech(='re%resh'4 'expnd'4 'collpse'>4 %unction(i4 e$) *
2
L('O' ' e$).clic#(%unction(e) * L('Ot"itter
di$.results').trigger(e$); +);
3 +);
-
( L('Ore!o$e').clic#(%unction(e) *
) i% (con%ir!('Ie!o$e ll resultsA')) *
5 L('Ot"itter di$.results').trigger('re!o$e'4 = true >);
6 +
8 +);
Conclusion
Custom events o%%er a ne( (ay o% thining about your code4 they put the emphasis on the
target o% a behavior& not on the element that triggers it" +% you tae the time at the outset to
spell out the pieces o% your application& as (ell as the behaviors those pieces need to
e'hibit& custom events can provide a po(er%ul (ay %or you to PtalQ to those pieces& either
one at a time or en masse" 3nce the behaviors o% a piece have been described& it becomes
trivial to trigger those behaviors %rom any(here& allo(ing %or rapid creation o% and
e'perimentation (ith inter%ace options" ,inally& custom events can enhance code
readability and maintainability& by maing clear the relationship bet(een an element and
its behaviors"
$ou can see the %ull application at demosKcustom-events"html and demosK.sKcustom-
events".s in the sample code"
Look out for more great tutorial downloads at: WebmasterJuice.com

Você também pode gostar