Jquery Cookbook
Jquery Cookbook
jQuery Cookbook
jQucry Community Expcrts
Beijing Cambridge Farnham Kln Sebastopol Taipei Tokyo
jQuery Cookbook
Ly jQueiy Community Expeits
Copyiight 2010 Couy Linuley. All iights ieseiveu.
Piinteu in the Uniteu States ol Ameiica.
PuLlisheu Ly O`Reilly Meuia, Inc., 1005 Giavenstein Highway Noith, SeLastopol, CA 95+72.
O`Reilly Looks may Le puichaseu loi euucational, Lusiness, oi sales piomotional use. Online euitions
aie also availaLle loi most titles (http://ny.sajariboo|son|inc.con). Foi moie inloimation, contact oui
coipoiate/institutional sales uepaitment: S00-99S-993S oi corporatcorci||y.con.
Editor: Simon St.Lauient
Production Editor: Saiah Schneiuei
Copyeditor: Kim Vimpsett
Proofreader: Anuiea Fox
Production Services: Molly Shaip
Indexer: Fieu Biown
Cover Designer: Kaien Montgomeiy
Interior Designer: Daviu Futato
Illustrator: RoLeit Romano
Printing History:
NovemLei 2009: Fiist Euition.
O`Reilly anu the O`Reilly logo aie iegisteieu tiauemaiks ol O`Reilly Meuia, Inc. jQucry Coo|boo|, the
image ol an eimine, anu ielateu tiaue uiess aie tiauemaiks ol O`Reilly Meuia, Inc.
Many ol the uesignations useu Ly manulactuieis anu selleis to uistinguish theii piouucts aie claimeu as
tiauemaiks. Vheie those uesignations appeai in this Look, anu O`Reilly Meuia, Inc. was awaie ol a
tiauemaik claim, the uesignations have Leen piinteu in caps oi initial caps.
Vhile eveiy piecaution has Leen taken in the piepaiation ol this Look, the puLlishei anu authoi assume
no iesponsiLility loi eiiois oi omissions, oi loi uamages iesulting liom the use ol the inloimation con-
taineu heiein.
TM
This Look uses RepKovei, a uuiaLle anu llexiLle lay-llat Linuing.
ISBN: 97S-0-596-15977-1
S
125777++09
Table of Contents
Foreword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi
Contributors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii
1. jQuery Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1 Incluuing the jQueiy LiLiaiy Coue in an HTML Page 9
1.2 Executing jQueiy/]avaSciipt Coueu Altei the DOM Has Loaueu
Lut Beloie Complete Page Loau 10
1.3 Selecting DOM Elements Using Selectois anu the jQueiy Function 13
1.+ Selecting DOM Elements Vithin a Specilieu Context 15
1.5 Filteiing a Viappei Set ol DOM Elements 16
1.6 Finuing Descenuant Elements Vithin the Cuiiently Selecteu
Viappei Set 1S
1.7 Retuining to the Piioi Selection Beloie a Destiuctive Change 19
1.S Incluuing the Pievious Selection with the Cuiient Selection 20
1.9 Tiaveising the DOM Baseu on Youi Cuiient Context to Acguiie a
New Set ol DOM Elements 21
1.10 Cieating, Opeiating on, anu Inseiting DOM Elements 23
1.11 Removing DOM Elements 2+
1.12 Replacing DOM Elements 26
1.13 Cloning DOM Elements 27
1.1+ Getting, Setting, anu Removing DOM Element AttiiLutes 29
1.15 Getting anu Setting HTML Content 30
1.16 Getting anu Setting Text Content 31
1.17 Using the $ Alias Vithout Cieating GloLal Conllicts 32
2. Selecting Elements with jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.1 Selecting Chilu Elements Only 36
2.2 Selecting Specilic SiLlings 37
v
2.3 Selecting Elements Ly Inuex Oiuei 39
2.+ Selecting Elements That Aie Cuiiently Animating +1
2.5 Selecting Elements Baseu on Vhat They Contain +2
2.6 Selecting Elements Ly Vhat They Don`t Match +3
2.7 Selecting Elements Baseu on Theii VisiLility +3
2.S Selecting Elements Baseu on AttiiLutes ++
2.9 Selecting Foim Elements Ly Type +6
2.10 Selecting an Element with Specilic Chaiacteiistics +7
2.11 Using the Context Paiametei +S
2.12 Cieating a Custom Filtei Selectoi 50
3. Beyond the Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.1 Looping Thiough a Set ol Selecteu Results 53
3.2 Reuucing the Selection Set to a Specilieu Item 56
3.3 Conveit a Selecteu jQueiy OLject into a Raw DOM OLject 59
3.+ Getting the Inuex ol an Item in a Selection 62
3.5 Making a Unigue Aiiay ol Values liom an Existing Aiiay 6+
3.6 Peiloiming an Action on a SuLset ol the Selecteu Set 67
3.7 Conliguiing jQueiy Not to Conllict with Othei LiLiaiies 69
3.S Auuing Functionality with Plugins 72
3.9 Deteimining the Exact Queiy That Vas Useu 7+
4. jQuery Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
+.1 Detecting Featuies with jQueiy.suppoit 77
+.2 Iteiating Ovei Aiiays anu OLjects with jQueiy.each 79
+.3 Filteiing Aiiays with jQueiy.giep S0
+.+ Iteiating anu Mouilying Aiiay Entiies with jQueiy.map S1
+.5 ComLining Two Aiiays with jQueiy.meige S1
+.6 Filteiing Out Duplicate Aiiay Entiies with jQueiy.unigue S2
+.7 Testing CallLack Functions with jQueiy.isFunction S2
+.S Removing Vhitespace liom Stiings oi Foim Values with
jQueiy.tiim S3
+.9 Attaching OLjects anu Data to DOM with jQueiy.uata S+
+.10 Extenuing OLjects with jQueiy.extenu S5
5. Faster, Simpler, More Fun . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
5.1 That`s Not jQueiy, It`s ]avaSciipt! S7
5.2 Vhat`s Viong with $(this)? SS
5.3 Removing Reuunuant Repetition 91
5.+ Foimatting Youi jQueiy Chains 92
5.5 Boiiowing Coue liom Othei LiLiaiies 9+
5.6 Viiting a Custom Iteiatoi 96
5.7 Toggling an AttiiLute 99
vi | Table of Contents
5.S Finuing the Bottlenecks 101
5.9 Caching Youi jQueiy OLjects 105
5.10 Viiting Fastei Selectois 107
5.11 Loauing TaLles Fastei 109
5.12 Couing Baie-Metal Loops 112
5.13 Reuucing Name Lookups 115
5.1+ Upuating the DOM Fastei with .inneiHTML 117
5.15 DeLugging? Bieak Those Chains 11S
5.16 Is It a jQueiy Bug? 120
5.17 Tiacing into jQueiy 121
5.1S Making Fewei Seivei Reguests 123
5.19 Viiting UnoLtiusive ]avaSciipt 126
5.20 Using jQueiy loi Piogiessive Enhancement 12S
5.21 Making Youi Pages AccessiLle 130
6. Dimensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
6.1 Finuing the Dimensions ol the Vinuow anu Document 135
6.2 Finuing the Dimensions ol an Element 137
6.3 Finuing the Ollset ol an Element 139
6.+ Sciolling an Element into View 1+1
6.5 Deteimining Vhethei an Element Is Vithin the Viewpoit 1+3
6.6 Centeiing an Element Vithin the Viewpoit 1+6
6.7 ALsolutely Positioning an Element at Its Cuiient Position 1+7
6.S Positioning an Element Relative to Anothei Element 1+7
6.9 Switching Stylesheets Baseu on Biowsei Viuth 1+S
7. Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
7.1 Sliuing anu Fauing Elements in anu out ol View 153
7.2 Making Elements VisiLle Ly Sliuing Them Up 156
7.3 Cieating a Hoiizontal Accoiuion 157
7.+ Simultaneously Sliuing anu Fauing Elements 161
7.5 Applying Seguential Ellects 162
7.6 Deteimining Vhethei Elements Aie Cuiiently Being Animateu 16+
7.7 Stopping anu Resetting Animations 165
7.S Using Custom Easing Methous loi Ellects 166
7.9 DisaLling All Ellects 16S
7.10 Using jQueiy UI loi Auvanceu Ellects 16S
8. Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
S.1 Attaching a Hanulei to Many Events 172
S.2 Reusing a Hanulei Function with Dilleient Data 173
S.3 Removing a Vhole Set ol Event Hanuleis 175
S.+ Tiiggeiing Specilic Event Hanuleis 176
Table of Contents | vii
S.5 Passing Dynamic Data to Event Hanuleis 177
S.6 Accessing an Element ASAP (Beloie uocument.ieauy) 179
S.7 Stopping the Hanulei Execution Loop 1S2
S.S Getting the Coiiect Element Vhen Using event.taiget 1S+
S.9 Avoiu Multiple hovei() Animations in Paiallel 1S5
S.10 Making Event Hanuleis Voik loi Newly Auueu Elements 1S7
9. Advanced Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
9.1 Getting jQueiy to Voik Vhen Loaueu Dynamically 191
9.2 Speeuing Up GloLal Event Tiiggeiing 192
9.3 Cieating Youi Own Events 195
9.+ Letting Event Hanuleis Pioviue Neeueu Data 19S
9.5 Cieating Event-Diiven Plugins 201
9.6 Getting Notilieu Vhen jQueiy Methous Aie Calleu 205
9.7 Using OLjects` Methous as Event Listeneis 20S
10. HTML Form Enhancements from Scratch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
10.1 Focusing a Text Input on Page Loau 212
10.2 DisaLling anu EnaLling Foim Elements 213
10.3 Selecting Rauio Buttons Automatically 216
10.+ (De)selecting All CheckLoxes Using Deuicateu Links 21S
10.5 (De)selecting All CheckLoxes Using a Single Toggle 219
10.6 Auuing anu Removing Select Options 221
10.7 AutotaLLing Baseu on Chaiactei Count 222
10.S Displaying Remaining Chaiactei Count 22+
10.9 Constiaining Text Input to Specilic Chaiacteis 226
10.10 SuLmitting a Foim Using Ajax 22S
10.11 Valiuating Foims 229
11. HTML Form Enhancements with Plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
11.1 Valiuating Foims 23S
11.2 Cieating Maskeu Input Fielus 2+7
11.3 Autocompleting Text Fielus 2+9
11.+ Selecting a Range ol Values 250
11.5 Enteiing a Range-Constiaineu Value 253
11.6 Uploauing Files in the Backgiounu 255
11.7 Limiting the Length ol Text Inputs 256
11.S Displaying LaLels ALove Input Fielus 257
11.9 Giowing an Input with Its Content 259
11.10 Choosing a Date 260
12. jQuery Plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
12.1 Vheie Do You Finu jQueiy Plugins? 263
viii | Table of Contents
12.2 Vhen Shoulu You Viite a jQueiy Plugin? 265
12.3 Viiting Youi Fiist jQueiy Plugin 267
12.+ Passing Options into Youi Plugin 26S
12.5 Using the $ Shoitcut in Youi Plugin 270
12.6 Incluuing Piivate Functions in Youi Plugin 272
12.7 Suppoiting the Metauata Plugin 273
12.S Auuing a Static Function to Youi Plugin 275
12.9 Unit Testing Youi Plugin with QUnit 277
13. Interface Components from Scratch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
13.1 Cieating Custom Tool Tips 2S0
13.2 Navigating with a File-Tiee Expanuei 2S5
13.3 Expanuing an Accoiuion 2SS
13.+ TaLLing Thiough a Document 293
13.5 Displaying a Simple Moual Vinuow 296
13.6 Builuing Diop-Down Menus 303
13.7 Cioss-Fauing Rotating Images 305
13.S Sliuing Panels 310
14. User Interfaces with jQuery UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
1+.1 Incluuing the Entiie jQueiy UI Suite 317
1+.2 Incluuing an Inuiviuual jQueiy UI Plugin oi Two 31S
1+.3 Initializing a jQueiy UI Plugin with Delault Options 319
1+.+ Initializing a jQueiy UI Plugin with Custom Options 320
1+.5 Cieating Youi Veiy Own jQueiy UI Plugin Delaults 321
1+.6 Getting anu Setting jQueiy UI Plugin Options 323
1+.7 Calling jQueiy UI Plugin Methous 323
1+.S Hanuling jQueiy UI Plugin Events 32+
1+.9 Destioying a jQueiy UI Plugin 326
1+.10 Cieating a jQueiy UI Music Playei 327
15. jQuery UI Theming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
15.1 Styling jQueiy UI Viugets with ThemeRollei 3+5
15.2 Oveiiiuing jQueiy UI Layout anu Theme Styles 360
15.3 Applying a Theme to Non-jQueiy UI Components 370
15.+ Releiencing Multiple Themes on a Single Page 379
15.5 Appenuix: Auuitional CSS Resouices 3SS
16. jQuery, Ajax, Data Formats: HTML, XML, JSON, JSONP . . . . . . . . . . . . . . . . . . . . . . . 391
16.1 jQueiy anu Ajax 391
16.2 Using Ajax on Youi Vhole Site 39+
16.3 Using Simple Ajax with Usei FeeuLack 396
16.+ Using Ajax Shoitcuts anu Data Types +00
Table of Contents | ix
16.5 Using HTML Fiagments anu jQueiy +03
16.6 Conveiting XML to DOM +0+
16.7 Cieating ]SON +05
16.S Paising ]SON +06
16.9 Using jQueiy anu ]SONP +07
17. Using jQuery in Large Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
17.1 Using Client-Siue Stoiage +11
17.2 Saving Application State loi a Single Session +1+
17.3 Saving Application State Between Sessions +16
17.+ Using a ]avaSciipt Template Engine +17
17.5 Queuing Ajax Reguests +20
17.6 Dealing with Ajax anu the Back Button +22
17.7 Putting ]avaSciipt at the Enu ol a Page +23
18. Unit Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
1S.1 Automating Unit Testing +25
1S.2 Asseiting Results +27
1S.3 Testing Synchionous CallLacks +29
1S.+ Testing Asynchionous CallLacks +29
1S.5 Testing Usei Actions +31
1S.6 Keeping Tests Atomic +32
1S.7 Giouping Tests +33
1S.S Selecting Tests to Run +3+
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
x | Table of Contents
Foreword
Vhen I liist staiteu woik on Luiluing jQueiy, Lack in 2005, I hau a simple goal in minu:
I wanteu to Le aLle to wiite a weL application anu have it woik in all the majoi
Liowseiswithout luithei tinkeiing anu Lug lixing. It was a couple ol months Leloie
I hau a set ol utilities that weie staLle enough to achieve that goal loi my peisonal use.
I thought I was ielatively uone at this point; little uiu I know that my woik was just
Leginning.
Since those simple Leginnings, jQueiy has giown anu auapteu as new useis use the
liLiaiy loi theii piojects. This has pioven to Le the most challenging pait ol ueveloping
a ]avaSciipt liLiaiy; while it is guite easy to Luilu a liLiaiy that`ll woik loi youisell oi
a specilic application, it Lecomes incieuiLly challenging to uevelop a liLiaiy that`ll woik
in as many enviionments as possiLle (olu Liowseis, legacy weL pages, anu stiange
maikup aLounu). Suipiisingly, even as jQueiy has auapteu to hanule moie use cases,
most ol the oiiginal API has stayeu intact.
One thing I linu paiticulaily inteiesting is to see how uevelopeis use jQueiy anu make
it theii own. As someone with a Lackgiounu in computei science, I linu it guite sui-
piising that so many uesigneis anu nonpiogiammeis linu jQueiy to Le compelling.
Seeing how they inteiact with the liLiaiy has given me a Lettei appieciation ol simple
API uesign. Auuitionally, seeing many auvanceu piogiammeis take jQueiy anu uevelop
laige, complex applications with it has Leen guite illuminating. The Lest pait ol all ol
this, though, is the aLility to leain liom eveiyone who uses the liLiaiy.
A siue Lenelit ol using jQueiy is its extensiLle plugin stiuctuie. Vhen I liist uevelopeu
jQueiy, I was suie to incluue some simple ways loi uevelopeis to extenu the API that
it pioviueu. This has Llossomeu into a laige anu vaiieu community ol plugins, encom-
passing a whole ecosystem ol applications, uevelopeis, anu use cases. Much ol jQueiy`s
giowth has Leen lueleu Ly this communitywithout it, the liLiaiy woulun`t Le wheie
it is touay, so I`m glau that theie aie chapteis ueuicateu to some ol the most inteiesting
plugins anu what you can uo with them. One ol the Lest ways to expanu youi piecon-
ceiveu notion ol what you can uo with jQueiy is to leain anu use coue liom the jQueiy
plugin community.
xi
This is laigely what makes something like a cookLook so inteiesting: it takes the cool
things that uevelopeis have uone, anu have leaineu, in theii uay-to-uay couing anu
uistills it to Lite-sizeu chunks loi latei consumption. Peisonally, I linu a cookLook to
Le one ol the Lest ways to challenge my pieconceiveu notions ol a language oi liLiaiy.
I love seeing cases wheie an API that I thought I knew well is tuineu aiounu anu useu
in new anu inteiesting ways. I hope this Look is aLle to seive you well, teaching you
new anu inteiesting ways to use jQueiy.
]ohn Resig
Cieatoi, Leau Developei, jQueiy
xii | Foreword
Contributors
Chapter Authors
-RQDWKDQ6KDUS has Leen passionate aLout the Inteinet anu weL uevelopment since
1996. Ovei the yeais that have lolloweu, he has woikeu loi staitups anu loi Foitune
500 coipoiations. ]onathan lounueu Out Vest Meuia, LLC, in gieatei Omaha, Ne-
Liaska, anu pioviues liontenu engineeiing anu aichitectuie seivices with a locus on
custom XHTML, CSS, anu jQueiy uevelopment. ]onathan is a jQueiy coie team mem-
Lei anu an authoi anu piesentei when not couing. ]onathan is most giatelul loi his
wile, Eiin; uaughtei, Noel; two uogs, anu two hoises.
5RE%XUQV uevelops inteiactive weL applications at A Mountain Top, LLC. Foi the
past 12 yeais he has Leen exploiing weLsite uevelopment using a wiue iange ol tools
anu technologies. In his spaie time, he enjoys natuial-language piocessing anu the
wealth ol oppoitunity in open souice soltwaie piojects.
5HEHFFD0XUSKH\ is an inuepenuent liontenu aichitectuie consultant, cialting cus-
tom liontenu solutions that seive as the glue Letween seivei anu Liowsei. She also
pioviues tiaining in liontenu uevelopment, with an emphasis on the jQueiy liLiaiy.
She lives with hei paitnei, two uogs, anu two cats in Duiham, Noith Caiolina.
$ULHO)OHVOHU is a weL uevelopei anu a viueo game piogiammei. He`s Leen contiiLuting
to jQueiy since ]anuaiy 2007 anu joineu the coie team in May 200S. He is 23 yeais olu
anu was Loin in Buenos Aiies, Aigentina. He`s stuuying at the National Technological
Univeisity (Aigentina) anu is hoping to Lecome a systems analyst Ly 2010 anu a systems
engineei Ly 2012. He staiteu woiking as an ASP.NET(C=) piogiammei anu then
switcheu to client-siue uevelopment ol XHTML sites anu Ajax applications. He`s cui-
iently woiking at QB9 wheie he uevelops AS3-Laseu casual games anu MMOs.
&RG\/LQGOH\ is a Chiistian, husLanu, son, lathei, Liothei, outuooi enthusiast, anu
piolessional client-siue engineei. Since 1997 he has Leen passionate aLout HTML, CSS,
]avaSciipt, Flash, inteiaction uesign, inteilace uesign, anu HCI. He is most well known
in the jQueiy community loi the cieation ol ThickBox, a moual/uialog solution. In
200S he ollicially joineu the jQueiy team as an evangelist. His cuiient locus has Leen
xiii
on client-siue optimization technigues as well as speaking anu wiiting aLout jQueiy.
His weLsite is http://www.cody|ind|cy.con.
5HP\6KDUS is a uevelopei, authoi, speakei, anu Lloggei. Remy staiteu his piolessional
weL uevelopment caieei in 1999 as the sole uevelopei loi a linance weLsite anu, as
such, was exposeu to all aspects ol iunning the weLsite uuiing, anu long altei, the
uotcom Loom. Touay he iuns his own uevelopment company calleu Lelt Logic in
Biighton, UK, wiiting anu couing ]avaSciipt, jQueiy, HTML 5, CSS, PHP, Peil, anu
anything else he can get his hanus on.
0LNH+RVWHWOHU is an inventoi, entiepieneui, piogiammei, anu piouu lathei. Having
woikeu with weL technologies since the miu-1990s, Mike has hau extensive expeiience
ueveloping weL applications with PHP anu ]avaSciipt. Cuiiently, Mike woiks at the
helm ol A Mountain Top, LLC, a weL technology consulting liim in Denvei, Coloiauo.
Heavily involveu in open souice, Mike is a memLei ol the jQueiy coie team, leaus the
QCuLeu PHP5 Fiamewoik pioject, anu paiticipates in the Diupal pioject. Vhen not
in liont ol a computei, Mike enjoys hiking, lly lishing, snowLoaiuing, anu spenuing
time with his lamily.
5DOSK:KLWEHFN is a giauuate ol the Rochestei Institute ol Technology anu is cuiiently
a senioi uevelopei loi BianuLogic Coipoiation in Rochestei, New Yoik. His iespon-
siLilities at BianuLogic incluue inteilace uesign, usaLility testing, anu weL anu appli-
cation uevelopment. Ralph is aLle to piogiam complex weL application systems in
ASP.NET, C=, anu SQL Seivei anu also uses client-siue technologies such as XHTML,
CSS, anu ]avaSciipt/jQueiy in oiuei to implement client-appioveu uesigns. Ralph ol-
licially joineu the jQueiy team as an evangelist in OctoLei 2009. Ralph enjoys spenuing
time with his wile, Hope, anu his thiee Loys, Bianuon, ]oiuan, anu Ralphie. You can
linu out moie aLout Ralph on his peisonal Llog.
1DWKDQ6PLWK is a gooly guy who has Leen Luiluing weLsites since late last centuiy.
He enjoys hanu-couing HTML, CSS, anu ]avaSciipt. He also uaLLles in uesign anu
inloimation aichitectuie. He has wiitten loi online anu papei puLlications such as
AuoLe Developei Centei, Digital VeL, anu .NET Magazine. He has spoken at venues
incluuing AuoLe MAX, BiLleTech, Diupal Camp, Echo Conleience, Ministiy 2.0, Re-
liesh Dallas, anu VeLmastei ]am Session. Nathan woiks as a UX uevelopei at Fellow-
shipTech.com. He holus a Mastei ol Divinity uegiee liom AsLuiy Theological Semi-
naiy. He staiteu GouLit.com, a community iesouice aimeu at helping chuiches anu
ministiies make Lettei use ol the VeL. He also cieateu the 960 Giiu System, a liame-
woik loi sketching, uesigning, anu couing page layouts.
%ULDQ &KHUQH is a soltwaie uevelopei with moie than a uecaue ol expeiience Llue-
piinting anu Luiluing weL-Laseu applications, kiosks, anu high-tiallic e-commeice
weLsites. He is also the authoi ol the hoveiIntent jQueiy plugin. Vhen not geeking
out with coue, Biian can Le lounu Lallioom uancing, piacticing maitial aits, oi stuuying
Russian cultuie anu language.
xiv | Contributors
-|UQ=DHIIHUHU is a piolessional soltwaie uevelopei liom Cologne, Geimany. He cie-
ates application piogiamming inteilaces (APIs), giaphical usei inteilaces (GUIs), solt-
waie aichitectuies, anu uataLases, loi Loth weL anu uesktop applications. His woik
locuses on the ]ava platloim, while his client-siue sciipting ievolves aiounu jQueiy.
He staiteu contiiLuting to jQueiy in miu-2006 anu has since cocieateu anu maintaineu
QUnit, jQueiy`s unit testing liamewoik; ieleaseu anu maintaineu a hall uozen veiy
populai jQueiy plugins; anu contiiLuteu to jQueiy Looks as Loth authoi anu tech
ieviewei. He is also a leau uevelopei loi jQueiy UI.
-DPHV3DGROVH\ is an enthusiastic weL uevelopei anu Lloggei Laseu in Lonuon, UK.
He`s Leen ciazy aLout jQueiy since he liist uiscoveieu it; he`s wiitten tutoiials teaching
it, aiticles anu Llog posts uiscussing it, anu plenty ol plugins loi the community. ]ames`
plans loi the lutuie incluue a computei science uegiee liom the Univeisity ol Kent anu
a caieei that allows him to continually push Lounuaiies. His weLsite is http://jancs
.pado|scy.con.
6FRWW*RQ]iOH] is a weL application uevelopei living in Raleigh, Noith Caiolina, who
enjoys Luiluing highly uynamic systems anu llexiLle, scalaLle liamewoiks. He has Leen
contiiLuting to jQueiy since 2007 anu is cuiiently the uevelopment leau loi jQueiy UI,
jQueiy`s ollicial usei inteilace liLiaiy. Scott also wiites tutoiials aLout jQueiy anu
jQueiy UI on nemikoi.com anu speaks aLout jQueiy at conleiences.
0LFKDHO*HDU\ staiteu ueveloping soltwaie when euiting coue meant punching a papei
tape on a Teletype machine, anu stanuaius-compliant meant lollowing ECMA-10
Stanuaiu loi Data Inteichange on Puncheu Tape. Touay Mike is a weL anu Anuioiu
uevelopei with a paiticulai inteiest in wiiting last, clean, anu simple coue, anu he enjoys
helping othei uevelopeis on the jQueiy mailing lists. Mike`s iecent piojects incluue a
seiies ol 200S election iesult anu votei inloimation maps loi Google; anu StiataLogic,
a mashup ol tiauitional classioom wall maps anu atlases oveilaiu on Google Eaith. His
weLsite is http://ng.to.
0DJJLH:DFKV, 6FRWW-HKO, 7RGG3DUNHU, anu 3DWW\7RODQG aie Filament Gioup.
Togethei, they uesign anu uevelop highly lunctional usei inteilaces loi consumei- anu
Lusiness-oiienteu weLsites, wiieless uevices, anu installeu anu weL-Laseu applications,
with a specilic locus on ueliveiing intuitive anu usaLle expeiiences that aie also Lioauly
accessiLle. They aie sponsoi anu uesign leaus ol the jQueiy UI team, loi whom they
uesigneu anu uevelopeu ThemeRollei.com, anu they actively contiiLute to ongoing
uevelopment ol the ollicial jQueiy UI liLiaiy anu CSS Fiamewoik.
5LFKDUG':RUWK is a weL UI uevelopei. He is the ielease managei loi jQueiy UI anu
one ol its longest-contiiLuting uevelopeis. He is authoi oi coauthoi ol the Dialog,
PiogiessLai, SelectaLle, anu Sliuei plugins. Richaiu also enjoys speaking anu consulting
on jQueiy anu jQueiy UI aiounu the woilu. Richaiu is iaising a giowing lamily in
Noithein Viiginia (Vashington, D.C. suLuiLs) with his lovely wile, Nancy. They have
Leen Llesseu to uate with thiee Leautilul chiluien: Naomi, Ashei, anu Isaiah.
Richaiu`s weLsite is http://rdworth.org/.
Contributors | xv
Tech Editors
.DUO6ZHGEHUJ, altei having taught high school English, euiteu copy loi an auveitising
agency, anu owneu a collee house, Legan his caieei as a weL uevelopei loui yeais ago.
He now woiks loi Fusionaiy Meuia in Gianu Rapius, Michigan, wheie he specializes
in client-siue sciipting anu inteiaction uesign. Kail is a memLei ol the jQueiy pioject
team anu coauthoi ol Lcarning jQucry 1.3 anu jQucry Rcjcrcncc Guidc (Loth puLlisheu
Ly Packt). You can linu some ol his tips anu tutoiials at http://www.|carningjqucry.con.
'DYH0HWKYLQ is the chiel technology ollicei at PCPitstop.com anu one ol the lounuing
paitneis ol the company. He has Leen using jQueiy since 2006, is active on the jQueiy
help gioups, anu has contiiLuteu seveial populai jQueiy plugins incluuing Coinei anu
Splittei. Beloie joining PC Pitstop, Dave seiveu as executive euitoi at Loth PC Tcch
journa| anu Windows Magazinc, wheie he wiote a column on ]avaSciipt. He continues
to wiite loi seveial PC-ielateu weLsites incluuing InloimationVeek. Dave holus Lach-
eloi`s anu mastei`s uegiees in computei science liom the Univeisity ol Viiginia.
'DYLG6HUGXNH is a liontenu piogiammei who is iecently spenuing much ol his time
seivei siue. Altei piogiamming loi many yeais, he staiteu using jQueiy in late 2007
anu shoitly altei joineu the jQueiy coie team. Daviu is cuiiently cieating weLsites loi
linancial institutions anu Liinging the Lenelits ol jQueiy to ASP.NET enteipiise ap-
plications. Daviu lives in noithein Caliloinia wheie he ieceiveu a Lacheloi`s uegiee
liom the Univeisity ol Caliloinia at Beikeley in electiical engineeiing anu an MBA liom
St. Maiy`s College.
6FRWW0DUN is an enteipiise application aichitect at Meutionic. He woiks on weL-Laseu
peisonalizeu inloimation poitals anu tiansactional applications with an eye towaiu
maintaining high usaLility in a iegulateu enviionment. His key inteiest aieas at the
moment aie iich Inteinet applications anu multitouch usei inteilace technologies. Scott
lives in Minnesota with his lovely wile, two sons, anu a Llack laL. He Llogs aLout
technology at http://scottnar|.wordprcss.con anu long-uistance tiail iunning at http://
run|i|cnon|cy.con.
xvi | Contributors
Preface
The jQueiy liLiaiy has taken the liontenu uevelopment woilu Ly stoim. Its ueau-simple
syntax makes once-complicateu tasks uowniight tiivialenjoyaLle, even. Many a ue-
velopei has Leen guickly seuuceu Ly its elegance anu claiity. Il you`ve staiteu using the
liLiaiy, you`ie alieauy auuing iich, inteiactive expeiiences to youi piojects.
Getting staiteu is easy, Lut as is the case with many ol the tools we use to uevelop
weLsites, it can take months oi even yeais to lully appieciate the Lieauth anu uepth ol
the jQueiy liLiaiy. The liLiaiy is chock-lull ol leatuies you might nevei have known to
wish loi. Once you know aLout them, they can uiamatically change how you appioach
the pioLlems you`ie calleu upon to solve.
The goal ol this cookLook is to expose you, ueai ieauei, to the patteins anu piactices
ol some ol the leauing liontenu uevelopeis who use jQueiy in theii eveiyuay piojects.
Ovei the couise ol 1S chapteis, they`ll guiue you thiough solutions to pioLlems that
iange liom stiaightloiwaiu to complex. Vhethei you`ie a jQueiy newcomei oi a giiz-
zleu ]avaSciipt veteian, you`ie likely to gain new insight into hainessing the lull powei
ol jQueiy to cieate compelling, ioLust, high-peiloimance usei inteilaces.
Who This Book Is For
MayLe you`ie a uesignei who is intiigueu Ly the inteiactivity that jQueiy can pioviue.
MayLe you`ie a liontenu uevelopei who has woikeu with jQueiy Leloie anu wants to
see how othei people accomplish common tasks. MayLe you`ie a seivei-siue uevelopei
who`s lieguently calleu upon to wiite client-siue coue.
Tiuth Le tolu, this cookLook will Le valuaLle to anyone who woiks with jQueiyoi
who hopes to woik with jQueiy. Il you`ie just staiting out with the liLiaiy, you may
want to consiuei paiiing this Look with Lcarning jQucry 1.3 liom Packt, oi jQucry in
Action liom Manning. Il you`ie alieauy using jQueiy in youi piojects, this Look will
seive to enhance youi knowleuge ol the liLiaiy`s leatuies, hiuuen gems, anu
iuiosynciasies.
xvii
What Youll Learn
Ve`ll stait out Ly coveiing the Lasics anu geneial Lest piacticesincluuing jQueiy in
youi page, making selections, anu tiaveising anu manipulation. Even lieguent jQueiy
useis aie likely to pick up a tip oi two. Fiom theie, we move on to ieal-woilu use cases,
walking you thiough tiieu-anu-tiue (anu testeu) solutions to lieguent pioLlems
involving events, ellects, uimensions, loims, anu usei inteilace elements (with anu
without the help ol jQueiy UI). At the enu, we`ll take a look at testing youi jQueiy
applications anu integiating jQueiy into complex sites.
Along the way, you`ll leain stiategies loi leveiaging jQueiy to solve pioLlems that go
lai Leyonu the Lasics. Ve`ll exploie how to make the most ol jQueiy`s event manage-
ment system, incluuing custom events anu custom event uata; how to piogiessively
enhance loims; how to position anu ieposition elements on the page; how to cieate
usei inteilace elements such as taLs, accoiuions, anu mouals liom sciatch; how to cialt
youi coue loi ieauaLility anu maintainaLility; how to optimize youi coue to ease testing,
eliminate Lottlenecks, anu ensuie peak peiloimance; anu moie.
Because this is a cookLook anu not a manual, you`ie ol couise welcome to cheiiy-pick
the iecipes you ieau; the inuiviuual iecipes alone aie woith the piice ol aumission. As
a whole, though, the Look pioviues a iaie glimpse into the pioLlem-solving appioaches
ol some ol the Lest anu Liightest in the jQueiy community. Vith that in minu, we
encouiage you to at least skim it liom liont to Lackyou nevei know which line ol
coue will pioviue the Aha! moment you neeu to take youi skills to the next level.
jQuery Style and Conventions
jQueiy places a heavy emphasis on chainingcalling methous on element selections
in seguence, conliuent in the knowleuge that each methou will give you Lack a selection
ol elements you can continue to woik with. This pattein is explaineu in uepth in
Chaptei 1il you`ie new to the liLiaiy, you`ll want to unueistanu this concept, Lecause
it is useu heavily in suLseguent chapteis.
jQueiy`s leatuies aie oiganizeu into a hanulul ol simple categoiies: coie lunctionality,
selecting, manipulating, tiaveising, CSS, attiiLutes, events, ellects, Ajax, anu utilities.
Leaining these categoiies, anu how methous lit into them, will gieatly enhance youi
unueistanuing ol the mateiial in this Look.
One ol the Lest piactices this Look will covei is the concept ol stoiing element selections
in a vaiiaLle, iathei than making the same selection iepeateuly. Vhen a selection is
stoieu in a vaiiaLle, it is commonplace loi that vaiiaLle to Legin with the $ chaiactei,
inuicating that it is a jQueiy oLject. This can make coue easiei to ieau anu maintain,
Lut it shoulu Le unueistoou that staiting the vaiiaLle name with the $ chaiactei is meiely
a convention; it caiiies no special meaning, unlike in othei languages such as PHP.
xviii | Preface
In geneial, the coue examples in this Look stiive loi claiity anu ieauaLility ovei com-
pactness, so the examples may Le moie veiLose than is stiictly necessaiy. Il you see an
oppoitunity loi optimization, you shoulu not hesitate to take it. At the same time, you`ll
uo well to stiive loi claiity anu ieauaLility in youi own coue anu use minilication tools
to piepaie youi coue loi piouuction use.
Other Options
Il you`ie looking loi othei jQueiy iesouices, heie aie some we iecommenu:
Lcarning jQucry 1.3, Ly ]onathan Challei, Kail SweuLeig, anu ]ohn Resig (Packt)
jQucry in Action, Ly Beai BiLeault, Yehuua Katz, anu ]ohn Resig (Manning)
jQucry U| 1.: Thc Uscr |ntcrjacc Library jor jQucry, Ly Dan Vellman (Packt)
If You Have Problems Making Examples Work
Beloie you check anything else, ensuie that you aie loauing the jQueiy liLiaiy on the
pageyou`u Le suipiiseu how many times this is the solution to the It`s not woiking!
pioLlem. Il you aie using jQueiy with anothei ]avaSciipt liLiaiy, you may neeu to use
jQuery.noConflict() to make it play well with otheis. Il you`ie loauing sciipts that
ieguiie the piesence ol jQueiy, make suie you aie loauing them altei you`ve loaueu the
jQueiy liLiaiy.
Much ol the coue in this Look ieguiies the uocument to Le ieauy Leloie ]avaSciipt
can inteiact with it. Il you`ve incluueu coue in the heau ol the uocument, make suie
youi coue is encloseu in $(document).ready(function() { ... }); so that it knows to
wait until the uocument is ieauy loi inteiaction.
Some ol the leatuies uiscusseu in this Look aie availaLle only in jQueiy 1.3 anu latei.
Il you aie upgiauing liom an oluei veision ol jQueiy, make suie you`ve upgiaueu any
plugins you`ie using as welloutuateu plugins can leau to unpieuictaLle Lehavioi.
Il you`ie having uilliculty getting an example to woik in an existing application, make
suie you can get the example woiking on its own Leloie tiying to integiate it with youi
existing coue. Il that woiks, tools such as FiieLug loi the Fiielox Liowsei can Le uselul
in iuentilying the souice ol the pioLlem.
Il you`ie incluuing a minilieu veision ol jQueiy anu iunning into eiiois that point to
the jQueiy liLiaiy itsell, you may want to consiuei switching to the lull veision ol
jQueiy while you aie ueLugging the issue. You`ll have a much easiei time locating the
line that is causing you tiouLle, which will olten leau you in the uiiection ol a solution.
Il you`ie still stuck, consiuei posting youi guestion to the jQueiy Google gioup. Many
ol this Look`s authois aie iegulai paiticipants in the gioup, anu moie olten than not,
someone in the gioup will Le aLle to ollei uselul auvice. The #jquery IRC channel on
Fieenoue is anothei valuaLle iesouice loi tiouLleshooting issues.
Preface | xix
Il none ol this woiks, it`s possiLle we maue a mistake. Ve woikeu haiu to test anu
ieview all ol the coue in the Look, Lut eiiois uo cieep thiough. Check the eiiata (ue-
sciiLeu in the next section) anu uownloau the sample coue, which will Le upuateu to
auuiess any eiiata we uiscovei.
If You Like (or Dont Like) This Book
Il you likeoi uon`t likethis Look, Ly all means, please let people know. Amazon
ieviews aie one populai way to shaie youi happiness (oi lack ol happiness), oi you can
leave ieviews at the site loi the Look:
http://orci||y.con/cata|og/978059159771/
Theie`s also a link to eiiata theie. Eiiata gives ieaueis a way to let us know aLout typos,
eiiois, anu othei pioLlems with the Look. That eiiata will Le visiLle on the page im-
meuiately, anu we`ll conliim it altei checking it out. O`Reilly can also lix eiiata in lutuie
piintings ol the Look anu on Salaii, making loi a Lettei ieauei expeiience pietty guickly.
Ve hope to keep this Look upuateu loi lutuie veisions ol jQueiy, anu will also incoi-
poiate suggestions anu complaints into lutuie euitions.
Conventions Used in This Book
The lollowing typogiaphical conventions aie useu in this Look:
|ta|ic
Inuicates Inteinet auuiesses, such as uomain names anu URLs, anu new items
wheie they aie uelineu.
Constant width
Inuicates commanu lines anu options that shoulu Le typeu veiLatim; names anu
keywoius in piogiams, incluuing methou names, vaiiaLle names, anu class names;
anu HTML element tags, switches, attiiLutes, keys, lunctions, types, namespaces,
mouules, piopeities, paiameteis, values, oLjects, events, event hanuleis, macios,
the contents ol liles, oi the output liom commanus.
Constant width bold
Inuicates emphasis in piogiam coue lines.
Constant width italic
Inuicates text that shoulu Le ieplaceu with usei-supplieu values.
This icon signilies a tip, suggestion, oi geneial note.
xx | Preface
This icon inuicates a waining oi caution.
Using Code Examples
This Look is heie to help you get youi joL uone. In geneial, you may use the coue in
this Look in youi piogiams anu uocumentation. You uo not neeu to contact us loi
peimission unless you`ie iepiouucing a signilicant poition ol the coue. Foi example,
wiiting a piogiam that uses seveial chunks ol coue liom this Look uoes not ieguiie
peimission. Answeiing a guestion Ly citing this Look anu guoting example coue uoes
not ieguiie peimission. Selling oi uistiiLuting a CD-ROM ol examples liom O`Reilly
Looks docs ieguiie peimission. Incoipoiating a signilicant amount ol example coue
liom this Look into youi piouuct`s uocumentation docs ieguiie peimission.
Ve appieciate, Lut uo not ieguiie, attiiLution. An attiiLution usually incluues the title,
authoi, puLlishei, anu ISBN. Foi example: jQucry Coo|boo|, Ly Couy Linuley. Copy-
iight 2010 Couy Linuley, 97S-0-596-15977-1. Il you leel youi use ol coue examples
lalls outsiue laii use oi the peimission given aLove, leel liee to contact us at
pcrnissionsorci||y.con.
Safari Books Online
Salaii Books Online is an on-uemanu uigital liLiaiy that lets you easily
seaich ovei 7,500 technology anu cieative ieleience Looks anu viueos to
linu the answeis you neeu guickly.
Vith a suLsciiption, you can ieau any page anu watch any viueo liom oui liLiaiy online.
Reau Looks on youi cell phone anu moLile uevices. Access new titles Leloie they aie
availaLle loi piint, anu get exclusive access to manusciipts in uevelopment anu post
leeuLack loi the authois. Copy anu paste coue samples, oiganize youi lavoiites, uown-
loau chapteis, Lookmaik key sections, cieate notes, piint out pages, anu Lenelit liom
tons ol othei time-saving leatuies.
O`Reilly Meuia has uploaueu this Look to the Salaii Books Online seivice. To have lull
uigital access to this Look anu otheis on similai topics liom O`Reilly anu othei puL-
lisheis, sign up loi liee at http://ny.sajariboo|son|inc.con.
How to Contact Us
Please auuiess comments anu guestions conceining this Look to the puLlishei:
O`Reilly Meuia, Inc.
1005 Giavenstein Highway Noith
SeLastopol, CA 95+72
Preface | xxi
S00-99S-993S (in the Uniteu States oi Canaua)
707-S29-0515 (inteinational oi local)
707-S29-010+ (lax)
To comment oi ask technical guestions aLout this Look, senu email to:
boo|qucstionsorci||y.con
Foi moie inloimation aLout oui Looks, conleiences, Resouice Centeis, anu the
O`Reilly Netwoik, see oui weLsite at:
http://orci||y.con
ReLecca Muiphey anu Couy Linuley
xxii | Preface
CHAPTER 1
jQuery Basics
Cody Lindlcy
1.0 Introduction
Since you`ve pickeu up a cookLook aLout jQueiy, the authois ol this Look loi the most
pait aie going to assume that you have a loose iuea aLout what exactly jQueiy is anu
what it uoes. Fiankly, cookLooks in geneial aie typically wiitten loi an auuience who
seeks to enhance a lounuation ol knowleuge that has alieauy Leen estaLlisheu. Thus,
the iecipe-solution-uiscussion loimat is useu to guickly get you solutions to common
pioLlems. Howevei, il you aie a jQueiy newLie, uon`t thiow this Look against the wall
anu cuise us just yet. Ve`ve ueuicateu this chaptei to you.
Il you aie in neeu ol a ieview oi aie jumping into this cookLook with little oi no woiking
knowleuge ol jQueiy, this liist chaptei alone (the othei chapteis assume you know the
Lasics) will aiu you in leaining the jQueiy essentials. Now, iealistically, il you have
aLsolutely zeio knowleuge ol ]avaSciipt anu the DOM, you might want to take a step
Lack anu ask youisell whethei appioaching jQueiy without a Lasic unueistanuing ol
the ]avaSciipt coie language anu its ielationship with the DOM is plausiLle. It woulu
Le my iecommenuation to stuuy up on the DOM anu ]avaSciipt coie Leloie appioach-
ing jQueiy. I highly iecommenu javaScript: Thc Dcjinitivc Guidc Ly Daviu Flanagan
(O`Reilly) as a piimei Leloie ieauing this Look. But uon`t let my humLle opinion stop
you il you aie attempting to leain jQueiy Leloie you leain aLout the DOM anu ]ava-
Sciipt. Many have come to a woiking knowleuge ol these technologies Ly way ol
jQueiy. Anu while not iueal, let`s lace it, it can still Le uone.
Vith that saiu, let`s take a look at a loimal uelinition ol jQueiy anu a Liiel uesciiption
ol its lunctionality:
jQueiy is an open souice ]avaSciipt liLiaiy that simplilies the inteiactions Letween an
HTML uocument, oi moie piecisely the Document OLject Mouel (aka the DOM), anu
]avaSciipt.
In plain woius, anu loi the olu-school ]avaSciipt hackeis out theie, jQueiy makes Dy-
namic HTML (DHTML) ueau easy. Specilically, jQueiy simplilies HTML uocument
1
tiaveising anu manipulation, Liowsei event hanuling, DOM animations, Ajax intei-
actions, anu cioss-Liowsei ]avaSciipt uevelopment.
Vith a loimal explanation ol jQueiy unuei oui Lelts, let`s next exploie why you might
choose to use jQueiy.
Why jQuery?
It might seem a Lit silly to speak aLout the meiits ol jQueiy within this cookLook,
especially since you`ie ieauing this cookLook anu aie likely alieauy awaie ol the meiits.
So, while I might Le pieaching to the choii heie, we`ie going to take a guick look at
why a uevelopei might choose to use jQueiy. My point in uoing this is to lostei youi
Lasic knowleuge ol jQueiy Ly liist explaining the why Leloie we look at the how.
In Luiluing a case loi jQueiy, I`m not going to compaie jQueiy to its competitois in
oiuei to elevate jQueiy`s signilicance. That`s Lecause I just uon`t Lelieve that theie
ieally is a uiiect competitoi. Also, I Lelieve the only liLiaiy availaLle touay that meets
the neeus ol Loth uesignei types anu piogiammei types is jQueiy. In this context,
jQueiy is in a class ol its own.
Ol the notoiious ]avaSciipt liLiaiies anu liamewoiks in the wilu, I tiuly Lelieve each
has its own niche anu value. A Lioau compaiison is silly, Lut it`s neveitheless attempteu
all the time. Heck, I am even guilty ol it mysell. Howevei, altei much thought on the
topic, I tiuly Lelieve that all ]avaSciipt liLiaiies aie goou at something. They all have
value. Vhat makes one moie valuaLle than the othei uepenus moie upon who is using
it anu how it`s Leing useu than what it actually uoes. Besiues, it has Leen my oLseivation
that micio uilleiences acioss ]avaSciipt liLiaiies aie olten tiivial in consiueiation ol the
Lioauei goals ol ]avaSciipt uevelopment. So, without luithei philosophical iamLlings,
heie is a list ol attiiLutes that Luilus a case loi why you shoulu use jQueiy:
It`s open souice, anu the pioject is licenseu unuei an MIT anu a GNU Geneial
PuLlic License (GPL) license. It`s liee, yo, in multiple ways!
It`s small (1S KB minilieu) anu gzippeu (11+ KB, uncompiesseu).
It`s incieuiLly populai, which is to say it has a laige community ol useis anu a
healthy amount ol contiiLutois who paiticipate as uevelopeis anu evangelists.
It noimalizes the uilleiences Letween weL Liowseis so that you uon`t have to.
It`s intentionally a lightweight lootpiint with a simple yet clevei plugin
aichitectuie.
Its iepositoiy ol plugins is vast anu has seen steauy giowth since jQueiy`s ielease.
Its API is lully uocumenteu, incluuing inline coue examples, which in the woilu
ol ]avaSciipt liLiaiies is a luxuiy. Heck, any uocumentation at all was a luxuiy loi
yeais.
It`s liienuly, which is to say it pioviues helplul ways to avoiu conllicts with othei
]avaSciipt liLiaiies.
2 | Chapter 1:jQuery Basics
Its community suppoit is actually laiily uselul, incluuing seveial mailing lists, IRC
channels, anu a lieakishly insane amount ol tutoiials, aiticles, anu Llog posts liom
the jQueiy community.
It`s openly uevelopeu, which means anyone can contiiLute Lug lixes, enhance-
ments, anu uevelopment help.
Its uevelopment is steauy anu consistent, which is to say the uevelopment team is
not aliaiu ol ieleasing upuates.
Its auoption Ly laige oiganizations has anu will continue to Lieeu longevity anu
staLility (e.g., Miciosolt, Dell, Bank ol Ameiica, Digg, CBS, Netllix).
It`s incoipoiating specilications liom the V3C Leloie the Liowseis uo. As an ex-
ample, jQueiy suppoits a goou majoiity ol the CSS3 selectois.
It`s cuiiently testeu anu optimizeu loi uevelopment on mouein Liowseis
(Chiome 1, Chiome Nightly, IE 6, IE 7, IE S, Opeia 9.6, Salaii 3.2, VeLKit Nightly,
Fiielox 2, Fiielox 3, Fiielox Nightly).
It`s uowniight poweilul in the hanus ol uesignei types as well as piogiammeis.
jQueiy uoes not uisciiminate.
Its elegance, methouologies, anu philosophy ol changing the way ]avaSciipt is
wiitten is Lecoming a stanuaiu in anu ol itsell. Consiuei just how many othei
solutions have Loiioweu the selectoi anu chaining patteins.
Its unexplainaLle Ly-piouuct ol leel-goou piogiamming is contagious anu ceitainly
unavoiuaLle; even the ciitics seem to lall in love with aspects ol jQueiy.
Its uocumentation has many outlets (e.g., API Liowsei, uashLoaiu apps, cheat
sheets) incluuing an ollline API Liowsei (AIR application).
It`s puiposely Lent to lacilitate unoLtiusive ]avaSciipt piactices.
It has iemaineu a ]avaSciipt liLiaiy (as opposeu to a liamewoik) at heait while at
the same time pioviuing a sistei pioject loi usei inteilace wiugets anu application
uevelopment (jQueiy UI).
Its leaining cuive is appioachaLle Lecause it Luilus upon concepts that most ue-
velopeis anu uesigneis alieauy unueistanu (e.g., CSS anu HTML).
It is my opinion that the comLination ol the aloiementioneu jQueiy points, anu not
any single attiiLute on its own, sets it apait liom all othei solutions. The total jQueiy
package is simply unmatcheu as a ]avaSciipt tool.
The jQuery Philosophy
The jQueiy philosophy is Viite less, uo moie. This philosophy can Le luithei Lioken
uown into thiee concepts:
Finuing some elements (via CSS selectois) anu uoing something with them (via
jQueiy methous)
Chaining multiple jQueiy methous on a set ol elements
1.0 Introduction | 3
Using the jQueiy wiappei anu implicit iteiation
Unueistanuing these thiee concepts in uetail is lounuational when it comes time to
wiite youi own jQueiy coue oi augment the iecipes lounu in this Look. Let`s examine
each ol these concepts in uetail.
Find some elements and do something with them
Oi moie specilically stateu, locate a set ol elements in the DOM, anu then uo something
with that set ol elements. Foi example, let`s examine a scenaiio wheie you want to hiue
a <div> liom the usei, loau some new text content into the hiuuen <div>, change an
attiiLute ol the selecteu <div>, anu then linally make the hiuuen <div> visiLle again.
This last sentence tianslateu into jQueiy coue woulu look something like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
</head>
<body>
<div>old content</div>
<script>
//hide all divs on the page
jQuery('div').hide();
//update the text contained inside of all divs
jQuery('div').text('new content');
//add a class attribute with a value of updatedContent to all divs
jQuery('div').addClass("updatedContent");
//show all divs on the page
jQuery('div').show();
</script>
</body>
</html>
Let`s step thiough these loui jQueiy statements:
Hiue the <div> element on the page so it`s hiuuen liom the usei`s view.
Replace the text insiue the hiuuen <div> with some new text (new content).
Upuate the <div> element with a new attiiLute (class) anu value (updatedContent).
Show the <div> element on the page so it`s visiLle again to the viewing usei.
Il the jQueiy coue at this point is mystical syntax to you, that`s OK. Ve`ll uive into the
Lasics with the liist iecipe in this chaptei. Again, what you neeu to take away liom this
coue example is the jQueiy concept ol linu some elements anu uo something with
4 | Chapter 1:jQuery Basics
them. In oui coue example, we lounu all the <div> elements in the HTML page using
the jQueiy lunction (jQuery()), anu then using jQueiy methous we uiu something with
them (e.g., hide(), text(), addClass(), show()).
Chaining
jQueiy is constiucteu in a mannei that will allow jQueiy methous to Le chaineu. Foi
example, why not linu an element once anu then chain opeiations onto that element?
Oui loimei coue example uemonstiating the Finu some elements anu uo something
with them concept coulu Le iewiitten to a single ]avaSciipt statement using chaining.
This coue, using chaining, can Le changeu liom this:
//hide all divs on the page
jQuery('div').hide();
//update the text contained inside of the div
jQuery('div').text('new content');
//add a class attribute with a value of updatedContent to all divs
jQuery('div').addClass("updatedContent");
//show all divs on the page
jQuery('div').show();
to this:
jQuery('div').hide().text('new content').addClass("updatedContent").show();
oi, with inuenting anu line Lieaks, to this:
jQuery('div')
.hide()
.text('new content')
.addClass("updatedContent")
.show();
Plainly speaking, chaining simply allows you to apply an enuless chain ol jQueiy meth-
ous on the elements that aie cuiiently selecteu (cuiiently wiappeu with jQueiy lunc-
tionality) using the jQueiy lunction. Behinu the scenes, the elements pieviously selecteu
Leloie a jQueiy methou was applieu aie always ietuineu so that the chain can continue.
As you will see in lutuie iecipes, plugins aie also constiucteu in this mannei (ietuining
wiappeu elements) so that using a plugin uoes not Lieak the chain.
Il it`s not immeuiately oLvious, anu Laseu on the coue in guestion, chaining also cuts
uown on piocessing oveiheau Ly selecting a set ol DOM elements only once, to then
Le opeiateu on numeious times Ly jQueiy methous Ly way ol chaining. Avoiuing un-
necessaiy DOM tiaveising is a ciitical pait ol page peiloimance enhancements. Vhen-
evei possiLle, ieuse oi cache a set ol selecteu DOM elements.
1.0 Introduction | 5
The jQuery wrapper set
A goou majoiity ol the time, il jQueiy is involveu, you`ie going to Le getting what is
known as a wrappcr. In othei woius, you`ll Le selecting DOM elements liom an HTML
page that will Le wiappeu with jQueiy lunctionality. Peisonally, I olten ielei to this as
a wiappei set oi wiappeu set Lecause it`s a set ol elements wiappeu with jQueiy
lunctionality. Sometimes this wiappei set will contain one DOM element; othei times
it will contain seveial. Theie aie even cases wheie the wiappei set will contain no
elements. In these situations, the methous/piopeities that jQueiy pioviues will lail
silently il methous aie calleu on an empty wiappei set, which can Le hanuy in avoiuing
unneeueu if statements.
Now, Laseu on the coue we useu to uemonstiate the Finu some elements anu uo
something with them concept, what uo you think woulu happen il we auueu multiple
<div> elements to the weL page? In the lollowing upuateu coue example, I have auueu
thiee auuitional <div> elements to the HTML page, loi a total ol loui <div> elements:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<script type="text/JavaScript" src="http://ajax.googleapis.com/ajax/libs/
jquery/1.3.0/jquery.min.js"></script> </head>
<body>
<div>old content</div>
<div>old content</div>
<div>old content</div>
<div>old content</div>
<script>
//hide all divs on the page
jQuery('div').hide().text('new content').addClass("updatedContent").show();
</script>
</body>
</html>
You may not have explicitly wiitten any piogiammatic loops heie, Lut guess what?
jQueiy is going to scan the page anu place all <div> elements in the wiappei set so that
the jQueiy methous I am using heie aie peiloimeu (aka implicit iteiation) on each
DOM element in the set. Foi example, the .hide() methou actually applies to each
element in the set. So il you look at oui coue again, you will see that each methou that
we use will Le applieu to each <div> element on the page. It`s as il you hau wiitten a
loop heie to invoke each jQueiy methou on each DOM element. The upuateu coue
example will iesult in each <div> in the page Leing hiuuen, lilleu with upuateu text,
given a new class value, anu then maue visiLle again.
Viapping youi heau aiounu (pun intenueu) the wiappei set anu its uelault looping
system (aka implicit iteiation) is ciitical loi Luiluing auvanceu concepts aiounu loop-
ing. ]ust keep in minu that a simple loop is occuiiing heie Leloie you actually uo any
auuitional looping (e.g., jQuery('div').each(function(){}). Oi anothei way to look at
6 | Chapter 1:jQuery Basics
this is each element in the wiappei will typically Le changeu Ly the jQueiy methou(s)
that aie calleu.
Something to keep in minu heie is theie aie scenaiios that you will leain aLout in the
coming chapteis wheie only the liist element, anu not all the elements in the wiappei
set, is allecteu Ly the jQueiy methou (e.g., attr()).
How the jQuery API Is Organized
Theie is no guestion that when I liist staiteu out with jQueiy, my main ieason loi
selecting it as my ]avaSciipt liLiaiy was simply that it hau Leen piopeily uocumenteu
(anu the gazillion plugins!). Latei, I iealizeu anothei lactoi that cementeu my love allaii
with jQueiy was the lact that the API was oiganizeu into logical categoiies. ]ust Ly
looking at how the API was oiganizeu, I coulu naiiow uown the lunctionality I neeueu.
Beloie you ieally get staiteu with jQueiy, I suggest visiting the uocumentation online
anu simply uigesting how the API is oiganizeu. By unueistanuing how the API is oi-
ganizeu, you`ll moie guickly navigate the uocumentation to the exact inloimation you
neeu, which is actually a signilicant auvantage given that theie aie ieally a lot ol uilleient
ways to coue a jQueiy solution. It`s so ioLust that it`s easy to get hung up on imple-
mentation Lecause ol the numLei ol solutions loi a single pioLlem. I`ve ieplicateu heie
loi you how the API is oiganizeu. I suggest memoiizing the API outline, oi at the veiy
least the top-level categoiies.
jQueiy Coie
The jQueiy Function
jQueiy OLject Accessois
Data
Plugins
InteiopeiaLility
Selectois
Basics
Hieiaichy
Basic Filteis
Content Filteis
VisiLility Filteis
AttiiLute Filteis
Chilu Filteis
Foims
Foim Filteis
AttiiLutes
1.0 Introduction | 7
Atti
Class
HTML
Text
Value
Tiaveising
Filteiing
Finuing
Chaining
Manipulation
Changing Contents
Inseiting Insiue
Inseiting Outsiue
Inseiting Aiounu
Replacing
Removing
Copying
CSS
CSS
Positioning
Height anu Viuths
Events
Page Loau
Event Hanuling
Live Events
Inteiaction Helpeis
Event Helpeis
Ellects
Basics
Sliuing
Fauing
Custom
Settings
Ajax
A]AX Reguests
8 | Chapter 1:jQuery Basics
A]AX Events
Misc.
Utilities
Biowsei anu Featuie Detection
Aiiay anu OLject Opeiations
Test Opeiations
Stiing Opeiations
Uils
Beloie we jump into a seguence ol Lasic jQueiy iecipes, I woulu like to mention that
the iecipes lounu in this chaptei Luilu on each othei. That is, theie is a logical loimation
ol knowleuge as you piogiess liom the liist iecipe to the last. It`s my suggestion, loi
youi liist ieauing ol these iecipes, that you ieau them in oiuei liom 1.1 to 1.17.
1.1 Including the jQuery Library Code in an HTML Page
Problem
You want to use the jQueiy ]avaSciipt liLiaiy on a weL page.
Solution
Theie aie cuiiently two iueal solutions loi emLeuuing the jQueiy liLiaiy in a weL page:
Use the Google-hosteu content ueliveiy netwoik (CDN) to incluue a veision ol
jQueiy (useu in this chaptei).
Downloau youi own veision ol jQueiy liom jQueiy.com anu host it on youi own
seivei oi local lilesystem.
Discussion
Incluuing the jQueiy ]avaSciipt liLiaiy isn`t any uilleient liom incluuing any othei
exteinal ]avaSciipt lile. You simply use the HTML <script> element anu pioviue the
element a value (URL oi uiiectoiy path) loi its src="" attiiLute, anu the exteinal lile
you aie linking to will Le incluueu in the weL page. Foi example, the lollowing is a
template that incluues the jQueiy liLiaiy that you can use to stait any jQueiy pioject:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
</head>
<body>
1.1 Including the jQuery Library Code in an HTML Page | 9
<script type="text/JavaScript">
alert('jQuery ' + jQuery.fn.jquery);
</script>
</body>
</html>
Notice that I am usinganu highly iecommenu using loi puLlic weL pagesthe
Google-hosteu minilieu veision ol jQueiy. Howevei, ueLugging ]avaSciipt eiiois in
minilieu coue is not iueal. Duiing coue uevelopment, oi on the piouuction site, it ac-
tually might Le Lettei to use the nonminilieu veision liom Google loi the puipose ol
ueLugging potential ]avaSciipt eiiois. Foi moie inloimation aLout using the Google-
hosteu veision ol jQueiy, you can visit the Ajax liLiaiies API site on the VeL at http://
codc.goog|c.con/apis/ajax|ibs/.
It`s ol couise also possiLle, anu mostly likely olu hat, to host a copy ol the jQueiy coue
youisell. In most ciicumstances, howevei, this woulu Le silly to uo Lecause Google has
Leen kinu enough to host it loi you. By using a Google-hosteu veision ol jQueiy, you
Lenelit liom a staLle, ieliaLle, high-speeu, anu gloLally availaLle copy ol jQueiy. As
well, you ieap the Lenelit ol uecieaseu latency, incieaseu paiallelism, anu Lettei cach-
ing. This ol couise coulu Le accomplisheu without using Google`s solution, Lut it woulu
most likely cost you a uime oi two.
Now, loi whatevei ieason, you might not want to use the Google-hosteu veision ol
jQueiy. You might want a customizeu veision ol jQueiy, oi youi usage might not
ieguiie/have access to an Inteinet connection. Oi, you simply might Lelieve that Google
is The Man anu wish not to suLmit to usage Lecause you aie a contiol lieak anu
conspiiacy lanatic. So, loi those who uo not neeu, oi simply who uo not want, to use
a Google-hosteu copy ol the jQueiy coue, jQueiy can Le uownloaueu liom
jQueiy.com anu hosteu locally on youi own seivei oi local lilesystem. Baseu on the
template I`ve pioviueu in this iecipe, you woulu simply ieplace the src attiiLute value
with a URL oi uiiectoiy path to the location ol the jQueiy ]avaSciipt lile you`ve uown-
loaueu.
1.2 Executing jQuery/JavaScript Coded After the DOM Has
Loaded but Before Complete Page Load
Problem
Mouein ]avaSciipt applications using unoLtiusive ]avaSciipt methouologies typically
execute ]avaSciipt coue only altei the DOM has Leen completely loaueu. Anu the ieality
ol the situation is that any DOM tiaveising anu manipulation will ieguiie that the DOM
is loaueu Leloie it can Le opeiateu on. Vhat`s neeueu is a way to ueteimine when the
client, most olten a weL Liowsei, has completely loaueu the DOM Lut has possiLly not
yet completely loaueu all assets such as images anu SVF liles. Il we weie to use the
window.onload event in this situation, the entiie uocument incluuing all assets woulu
10 | Chapter 1:jQuery Basics
neeu to Le completely loaueu Leloie the onload event liieu. That`s just too time-
consuming loi most weL suileis. Vhat`s neeueu is an event that will tell us when the
DOM alone is ieauy to Le tiaveiseu anu manipulateu.
Solution
jQueiy pioviues the ready() methou, which is a custom event hanulei that is typically
Lounu to the DOM`s uocument oLject. The ready() methou is passeu a single paiam-
etei, a lunction, that contains the ]avaSciipt coue that shoulu Le executeu once the
DOM is ieauy to Le tiaveiseu anu manipulateu. The lollowing is a simple example ol
this event opening an alert() winuow once the DOM is ieauy Lut Leloie the page is
completely loaueu:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
jQuery(document).ready(function(){//DOM not loaded, must use ready event
alert(jQuery('p').text());
});
</script>
</head>
<body>
<p>The DOM is ready!</p>
</body>
</html>
Discussion
The ready() event hanulei methou is jQueiy`s ieplacement loi using the ]avaSciipt coie
window.onload event. It can Le useu as many times as you like. Vhen using this custom
event, it`s auvisaLle that it Le incluueu in youi weL pages altei the inclusion ol stylesheet
ueclaiations anu incluues. Doing this will ensuie that all element piopeities aie coi-
iectly uelineu Leloie any jQueiy coue oi ]avaSciipt coue will Le executeu Ly the
ready() event.
Auuitionally, the jQueiy lunction itsell pioviues a shoitcut loi using the jQueiy custom
ieauy event. Using this shoitcut, the lollowing alert() example can Le iewiitten like so:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
jQuery(function(){ //DOM not loaded, must use ready event
1.2 Executing jQuery/JavaScript Coded After the DOM Has Loaded but Before Complete Page Load | 11
alert(jQuery('p').text());
});
</script>
</head>
<body>
<p>The DOM is ready!</p>
</body>
</html>
The use ol this custom jQueiy event is necessaiy only il ]avaSciipt has to Le emLeuueu
in the uocument llow at the top ol the page anu encapsulateu in the <head> element. I
simply avoiu the usage ol the ready() event Ly placing all ]avaSciipt incluues anu inline
coue Leloie the closing <body> element. I uo this loi two ieasons.
Fiist, mouein optimization technigues have ueclaieu that pages loau lastei when the
]avaSciipt is loaueu Ly the Liowsei at the enu ol a page paise. In othei woius, il you
put ]avaSciipt coue at the Lottom ol a weL page, then the Liowsei will loau eveiything
in liont ol it Leloie it loaus the ]avaSciipt. This is a goou thing Lecause most Liowseis
will typically stop piocessing othei loauing initiatives until the ]avaSciipt engine has
compileu the ]avaSciipt containeu in a weL page. It`s soit ol a Lottleneck in a sense
that you have ]avaSciipt at the top ol a weL page uocument. I iealize that loi some
situations it`s easiei to place ]avaSciipt in the <head> element. But honestly, I`ve nevei
seen a situation wheie this is aLsolutely ieguiieu. Any oLstacle that I`ve encounteieu
uuiing my uevelopment Ly placing ]avaSciipt at the Lottom ol the page has Leen easily
oveicome anu well woith the optimization gains.
Seconu, il speeuy weL pages aie oui goal, why wiap moie lunctionality aiounu a sit-
uation that can Le elevateu Ly simply moving the coue to the Lottom ol the page? Vhen
given the choice Letween moie coue oi less coue, I choose less coue. Not using the
ready() event iesults in using less coue, especially since less coue always iuns lastei
than moie coue.
Vith some iationale out ol the way, heie is an example ol oui alert() coue that uoes
not use the ready() event:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p>The DOM is ready!</p>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
alert(jQuery('p').text());//go for it the DOM is loaded
</script>
</body>
</html>
12 | Chapter 1:jQuery Basics
Notice that I have placeu all ol my ]avaSciipt Leloie the closing </body> element. Any
auuitional maikup shoulu Le placeu aLove the ]avaSciipt in the HTML uocument.
1.3 Selecting DOM Elements Using Selectors and the jQuery
Function
Problem
You neeu to select a single DOM element anu/oi a set ol DOM elements in oiuei to
opeiate on the element(s) using jQueiy methous.
Solution
jQueiy pioviues two options when you neeu to select element(s) liom the DOM. Both
options ieguiie the use ol the jQueiy lunction (jQuery() oi alias $()). The liist option,
which uses CSS selectois anu custom selectois, is Ly lai the most useu anu most elo-
guent solution. By passing the jQueiy lunction a stiing containing a selectoi expiession,
the lunction will tiaveise the DOM anu locate the DOM noues uelineu Ly the expies-
sion. As an example, the lollowing coue will select all the <a> elements in the HTML
uocument:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<a href='#'>link</a>
<a href='#'>link</a>
<a href='#'>link</a>
<a href='#'>link</a>
<a href='#'>link</a>
<a href='#'>link</a>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
//alerts there are 6 elements
alert('Page contains ' + jQuery('a').length + ' <a> elements!');
</script>
</body>
</html>
Il you weie to iun this HTML page in a weL Liowsei, you woulu see that the coue
executes a Liowsei alert() that inloims us that the page contains six <a> elements. I
passeu this value to the alert() methou Ly liist selecting all the <a> elements anu then
using the length piopeity to ietuin the numLei ol elements in the jQueiy wiappei set.
1.3 Selecting DOM Elements Using Selectors and the jQuery Function | 13
You shoulu Le awaie that the liist paiametei ol the jQueiy lunction, as we aie using it
heie, will also accept multiple expiessions. To uo this, simply sepaiate multiple selec-
tois with a comma insiue the same stiing that is passeu as the liist paiametei to the
jQueiy lunction. Heie is an example ol what that might look like:
jQuery('selector1, selector2, selector3').length;
Oui seconu option loi selecting DOM elements anu the less common option is to pass
the jQueiy lunction an actual ]avaSciipt ieleience to DOM element(s). As an example,
the lollowing coue will select all the <a> elements in the HTML uocument. Notice that
I`m passing the jQueiy lunction an aiiay ol <a> elements collecteu using the
getElementsByTagName DOM methou. This example piouuces the same exact iesults as
oui pievious coue example:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body bgcolor="yellow"> <!-- yes the attribute is depreciated, I know, roll
with it -->
<a href='#'>link</a>
<a href='#'>link</a>
<a href='#'>link</a>
<a href='#'>link</a>
<a href='#'>link</a>
<a href='#'>link</a>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
//alerts there are 6 elements
alert('Page contains ' + jQuery(document.getElementsByTagName('a')).length +
' <a> Elements, And has a '
+ jQuery(document.body).attr('bgcolor') + ' background');
</script>
</body>
</html>
Discussion
The heavy lilting that jQueiy is known loi is paitially Laseu on the selectoi engine,
Sizzle, that selects DOM element(s) liom an HTML uocument. Vhile you have the
option, anu it`s a nice option when you neeu it, passing the jQueiy lunction DOM
ieleiences is not what put jQueiy on eveiyone`s iauai. It`s the vast anu poweilul options
availaLle with selectois that make jQueiy so unigue.
Thioughout the iest ol the Look, you will linu poweilul anu ioLust selectois. Vhen
you see one, make suie you lully unueistanu its lunction. This knowleuge will seive
you well with lutuie couing enueavois using jQueiy.
14 | Chapter 1:jQuery Basics
1.4 Selecting DOM Elements Within a Specified Context
Problem
You neeu a ieleience to a single DOM element oi a set ol DOM elements in the context
ol anothei DOM element oi uocument in oiuei to opeiate on the element(s) using
jQueiy methous.
Solution
The jQueiy lunction when passeu a CSS expiession will also accept a seconu paiametei
that tells the jQueiy lunction to which context it shoulu seaich loi the DOM elements
Laseu on the expiession. The seconu paiametei in this case can Le a DOM ieleience,
jQueiy wiappei, oi uocument. In the lollowing coue, theie aie 12 <input> elements.
Notice how I use a specilic context, Laseu on the <form> element, to select only pai-
ticulai <input> elements:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form>
<input name="" type="checkbox" />
<input name="" type="radio" />
<input name="" type="text" />
<input name="" type="button" />
</form>
<form>
<input name="" type="checkbox" />
<input name="" type="radio" />
<input name="" type="text" />
<input name="" type="button" />
</form>
<input name="" type="checkbox" />
<input name="" type="radio" />
<input name="" type="text" />
<input name="" type="button" />
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
//searches within all form elements, using a wrapper for context, alerts "8 inputs"
alert('selected ' + jQuery('input',$('form')).length + ' inputs');
//search with the first form element, using DOM reference as the context, alerts
1.4 Selecting DOM Elements Within a Specified Context | 15
//"4 inputs"
alert('selected' + jQuery('input',document.forms[0]).length + ' inputs');
//search within the body element for all input elements using an expression,
//alerts "12 inputs"
alert('selected' + jQuery('input','body').length + ' inputs');
</script>
</body>
</html>
Discussion
It`s also possiLle, as mentioneu in the solution ol this iecipe, to select uocuments as
the context loi seaiching. Foi example, it`s possiLle to seaich within the context ol an
XML uocument that is sent Lack liom uoing an XHR ieguest (Ajax). You can linu moie
uetails aLout this usage in Chaptei 16.
1.5 Filtering a Wrapper Set of DOM Elements
Problem
You have a set ol selecteu DOM elements in a jQueiy wiappei set Lut want to iemove
DOM elements liom the set that uo not match a new specilieu expiession(s) in oiuei
to cieate a new set ol elements to opeiate on.
Solution
The jQueiy liltei methou, useu on a jQueiy wiappei set ol DOM elements, can excluue
elements that do not match a specilieu expiession(s). In shoit, the filter() methou
allows you to liltei the cuiient set ol elements. This is an impoitant uistinction liom
the jQueiy linu methou, which will ieuuce a wiappeu set ol DOM elements Ly linuing
(via a new selectoi expiession) new elements, incluuing chilu elements ol the cuiient
wiappeu set.
To unueistanu the liltei methou, let`s examine the lollowing coue:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<a href="#" class="external">link</a>
<a href="#" class="external">link</a>
<a href="#"></a>
<a href="#" class="external">link</a>
<a href="#" class="external">link</a>
<a href="#"></a></li>
16 | Chapter 1:jQuery Basics
<a href="#">link</a>
<a href="#">link</a>
<a href="#">link</a>
<a href="#">link</a>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
//alerts 4 left in the set
alert(jQuery('a').filter('.external').length + ' external links');
</script>
</body>
</html>
The HTML page in the coue example just shown contains a weL page with 10 <a>
elements. Those links that aie exteinal links aie given a class name ol external. Using
the jQueiy lunction, we select all <a> elements on the page. Then, using the liltei meth-
ou, all those elements that uo not have a class attiiLute value ol external aie iemoveu
liom the oiiginal set. Once the initial set ol DOM elements aie alteieu using the
filter() methou, I invoke the length piopeity, which will tell me how many elements
aie now in my new set altei the liltei has Leen applieu.
Discussion
It`s also possiLle to senu the filter() methou a lunction that can Le useu to liltei the
wiappeu set. Oui pievious coue example, which passes the filter() methou a stiing
expiession, can Le changeu to use a lunction insteau:
alert(
jQuery('a')
.filter(function(index){ return $(this).hasClass('external');})
.length + ' external links'
);
Notice that I am now passing the filter() methou an anonymous lunction. This lunc-
tion is calleu with a context egual to the cuiient element. That means when I use
$(this) within the lunction, I am actually ieleiiing to each DOM element in the wiap-
pei set. Vithin the lunction, I am checking each <a> element in the wiappei set to see
whethei the element has a class value (hasClass()) ol external. Il it uoes, Boolean tiue,
then keep the element in the set, anu il it uoesn`t (lalse), then iemove the element liom
the set. Anothei way to look at this is il the lunction ietuins lalse, then the element is
iemoveu. Il the lunction ietuins any othei uata value Lesiues lalse, then the element
will iemain in the wiappei set.
You may have noticeu that I have passeu the lunction a paiametei nameu index that I
am not using. This paiametei, il neeueu, can Le useu to ielei numeiically to the inuex
ol the element in the jQueiy wiappei set.
1.5 Filtering a Wrapper Set of DOM Elements | 17
1.6 Finding Descendant Elements Within the Currently
Selected Wrapper Set
Problem
You have a set ol selecteu DOM elements (oi a single element) anu want to linu ue-
scenuant (chiluien) elements within the context ol the cuiiently selecteu elements.
Solution
Use the .find() methou to cieate a new wiappei set ol elements Laseu on the context
ol the cuiient set anu theii uescenuants. Foi example, say that you have a weL page
that contains seveial paiagiaphs. Encapsulateu insiue ol these paiagiaphs aie woius
that aie emphasizeu (italic). Il you`u like to select only <em> elements containeu within
<p> elements, you coulu uo so like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p>Ut ad videntur facilisis <em>elit</em> cum. Nibh insitam erat facit
<em>saepius</em> magna. Nam ex liber iriure et imperdiet. Et mirum eros
iis te habent. </p>
<p>Claram claritatem eu amet dignissim magna. Dignissim quam elit facer eros
illum. Et qui ex esse <em>tincidunt</em> anteposuerit. Nulla nam odio ii
vulputate feugait.</p>
<p>In quis <em>laoreet</em> te legunt euismod. Claritatem <em>consuetudium</em>
wisi sit velit facilisi.</p>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
//alerts total italic words found inside of <p> elements
alert('The three paragraphs in all contain ' +
jQuery('p').find('em').length + '
italic words');
</script>
</body>
</html>
Keep in minu that we coulu have also wiitten this coue Ly passing a contextual ieleience
as a seconu paiametei to the jQueiy lunction:
alert('The three paragraphs in all contain ' + jQuery('em',$('p')).length +
' italic words');
Auuitionally, it`s woith mentioning that the last two coue examples aie uemonstiative
in puipose. It is likely moie logical, il not piagmatic, to use a CSS selectoi expiession
to select all the uescenuant italic elements containeu within the ancestoi <p> elements.
18 | Chapter 1:jQuery Basics
alert('The three paragraphs in all contain ' + jQuery('p em').length +
' italic words');
Discussion
The jQueiy .find() methou can Le useu to cieate a new set ol elements Laseu on context
ol the cuiient set ol DOM elements anu theii chiluien elements. People olten conluse
the use ol the .filter() methou anu .find() methou. The easiest way to iememLei
the uilleience is to keep in minu that .find() will opeiate/select the chiluien ol the
cuiient set while .filter() will only opeiate on the cuiient set ol elements. In othei
woius, il you want to change the cuiient wiappei set Ly using it as a context to luithei
select the chiluien ol the elements selecteu, use .find(). Il you only want to liltei the
cuiient wiappeu set anu get a new suLset ol the cuiient DOM elements in the set only,
use .filter(). To Loil this uown even moie, find() ietuins chiluien elements, while
filter() only lilteis what is in the cuiient wiappei set.
1.7 Returning to the Prior Selection Before a Destructive
Change
Problem
A uestiuctive jQueiy methou (e.g., filter() oi find()) that was useu on a set ol ele-
ments neeus to Le iemoveu so that the set piioi to the use ol the uestiuctive methou is
ietuineu to its pievious state anu can then Le opeiateu as il the uestiuctive methou hau
nevei Leen invokeu.
Solution
jQueiy pioviues the end() methou so that you can ietuin to the pievious set ol DOM
elements that weie selecteu Leloie using a uestiuctive methou. To unueistanu the
end() methou, let`s examine the lollowing HTML.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p>text</p>
<p class="middle">Middle <span>text</span></p>
<p>text</p>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
alert(jQuery('p').filter('.middle').length); //alerts 1
alert(jQuery('p').filter('.middle').end().length); //alerts 3
alert(jQuery('p').filter('.middle').find('span')
1.7 Returning to the Prior Selection Before a Destructive Change | 19
.end().end().length); //alerts 3
</script>
</body>
</html>
The liist alert() statement in the coue contains a jQueiy statement that will seaich the
uocument loi all <p> elements anu then apply filter() to the selecteu <p> elements in
the set selecting only the one(s) with a class ol middle. The length piopeity then iepoits
how many elements aie lelt in the set:
alert(jQuery('p').filter('.middle').length); //alerts 1
The next alert() statement makes use ol the end() methou. Heie we aie uoing eveiy-
thing we uiu in the piioi statement except that we aie unuoing the filter() methou
anu ietuining to the set ol elements containeu in the wiappei set Leloie the filter()
methou was applieu:
alert(jQuery('p').filter('.middle').end().length); //alerts 3
The last alert() statement uemonstiates how the end() methou is useu twice to iemove
Loth the filter() anu find() uestiuctive changes, ietuining the wiappei set to its oiig-
inal composition:
alert(jQuery('p').filter('.middle').find('span').end().end().length); //alerts 3
Discussion
Il the end() methou is useu anu theie weie no piioi uestiuctive opeiations peiloimeu,
an empty set is ietuineu. A uestiuctive opeiation is any opeiation that changes the
set ol matcheu jQueiy elements, which means any tiaveising oi manipulation methou
that ietuins a jQueiy oLject, incluuing add(), andSelf(), children(), closes(),
filter(), find(), map(), next(), nextAll(), not(), parent(), parents(), prev(),
prevAll(), siblings(), slice(), clone(), appendTo(), prependTo(), insertBefore(),
insertAfter(), anu replaceAll().
1.8 Including the Previous Selection with the Current Selection
Problem
You have just manipulateu a set ol elements in oiuei to acguiie a new set ol elements.
Howevei, you want to opeiate on the piioi set as well as the cuiient set.
Solution
You can comLine a piioi selection ol DOM elements with the cuiient selection Ly using
the andSelf() methou. Foi example, in the lollowing coue, we aie liist selecting all
<div> elements on the page. Next we manipulate this set ol elements Ly linuing all
<p> elements containeu within the <div> elements. Now, in oiuei to opeiate on Loth
the <div> anu the <p> elements lounu within the <div>, we coulu incluue the <div> into
20 | Chapter 1:jQuery Basics
the cuiient set Ly using andSelf(). Hau I omitteu the andSelf(), the Loiuei coloi woulu
have only Leen applieu to the <p> elements:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<div>
<p>Paragraph</p>
<p>Paragraph</p>
</div>
<script type="text/JavaScript" src="http://ajax.googleapis.com/
ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
jQuery('div').find('p').andSelf().css('border','1px solid #993300');
</script>
</body>
</html>
Discussion
Keep in minu that when you use the andSelf() methou, it will only auu into the cuiient
set Leing opeiateu on anu the piioi set, Lut not all piioi sets.
1.9 Traversing the DOM Based on Your Current Context to
Acquire a New Set of DOM Elements
Problem
You have selecteu a set ol DOM elements, anu Laseu on the position ol the selections
within the DOM tiee stiuctuie, you want to tiaveise the DOM to acguiie a new set ol
elements to opeiate on.
Solution
jQueiy pioviues a set ol methous loi tiaveising the DOM Laseu on the context ol the
cuiiently selecteu DOM element(s).
Foi example, let`s examine the lollowing HTML snippet:
<div>
<ul>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
</ul>
</div>
1.9 Traversing the DOM Based on Your Current Context to Acquire a New Set of DOM Elements | 21
Now, let`s select the seconu <li> element using the :eq() inuex custom selectoi:
//selects the second element in the set of <li>'s by index, index starts at 0
jQuery('li:eq(1)');
Ve now have a context, a staiting point within the HTML stiuctuie. Oui staiting point
is the seconu <li> element. Fiom heie we can go anywheiewell, almost anywheie.
Let`s see wheie we can go using a couple ol the methous jQueiy pioviues loi tiaveising
the DOM. Reau the comments in the coue loi claiilication:
jQuery('li:eq(1)').next() //selects the third <li>
jQuery('li:eq(1)').prev() //selects the first <li>
jQuery('li:eq(1)').parent() //selects the <ul>
jQuery('li:eq(1)').parent().children() //selects all <li>s
jQuery('li:eq(1)').nextAll() //selects all the <li>s after the second <li>
jQuery('li:eq(1)').prevAll() //selects all the <li>s before the second <li>
Keep in minu that these tiaveising methous piouuce a new wiappei set, anu to ietuin
to the pievious wiappei set, you can use end().
Discussion
The tiaveising methous shown thus lai have uemonstiateu simple tiaveises. Theie aie
two auuitional concepts that aie impoitant to know aLout tiaveising.
The liist concept anu likely most oLvious is that tiaveising methous can Le chaineu.
Let`s examine again the lollowing jQueiy statement liom eailiei:
jQuery('li:eq(1)').parent().children() //selects all <li>'s
Notice that I have tiaveiseu liom the seconu <li> element to the paient <ul> element
anu then again tiaveiseu liom the paient element to selecting all the chiluien elements
ol the <ul> element. The jQueiy wiappei set will now contain all the <li> elements
containeu within the <ul>. Ol couise, this is a contiiveu example loi the puipose ol
uemonstiating tiaveising methous. Hau we ieally wanteu a wiappei set ol just <li>
elements, it woulu have Leen much simplei to select all the <li> elements liom the
get-go (e.g., jQuery('li')).
The seconu concept that you neeu to keep in minu when uealing with the tiaveising
methous is that many ol the methous will accept an optional paiametei that can Le
useu to liltei the selections. Let`s take oui chaineu example again anu look at how we
coulu change it so that only the last <li> element was selecteu. Keep in minu that this
is a contiiveu example loi the puipose ol uemonstiating how a tiaveising methou can
Le passeu an expiession useu loi selecting a veiy specilic element:
jQuery('li:eq(1)').parent().children(':last') //selects the last <li>
22 | Chapter 1:jQuery Basics
jQueiy pioviues auuitional tiaveising methous that weie not shown heie. Foi a com-
plete list anu uocumentation, have a look at http://docs.jqucry.con/Travcrsing. You will
linu these auuitional tiaveising methous useu thioughout this Look.
1.10 Creating, Operating on, and Inserting DOM Elements
Problem
You want to cieate new DOM elements (oi a single element) that aie immeuiately
selecteu, opeiateu on, anu then injecteu into the DOM.
Solution
Il you haven`t liguieu it out yet, the jQueiy lunction is multilaceteu in that this one
lunction peiloims uilleiently uepenuing upon the makeup ol the paiametei(s) you senu
it. Il you pioviue the lunction with a text stiing ol iaw HTML, it will cieate these
elements loi you on the lly. Foi example, the lollowing statement will cieate an <a>
element wiappeu insiue ol a <p> element with a text noue encapsulateu insiue ol the
<p> anu <a> elements:
jQuery('<p><a>jQuery</a></p>');
Now, with an element cieateu, you can use jQueiy methous to luithei opeiate on the
elements you just cieateu. It`s as il you hau selecteu the <p> element liom the get-go in
an existing HTML uocument. Foi example, we coulu opeiate on the <a> Ly using
the .find() methou to select the <a> element anu then set one ol its attiiLutes. In the
case ol the lollowing coue, we aie setting the href attiiLute with a value ol http://
www.jquery.com:
jQuery('<p><a>jQuery</a></p>').find('a').attr('href','http://www.jquery.com');
This is gieat, iight? Vell, it`s aLout to get Lettei Lecause all we have uone so lai is cieate
elements on the lly anu manipulate those elements in coue. Ve have yet to actually
change the cuiiently loaueu DOM, so to speak. To uo this, we`ll have to use the ma-
nipulation methous pioviueu Ly jQueiy. The lollowing is oui coue in the context ol an
HTML uocument. Heie we aie cieating elements, opeiating on those elements, anu
then inseiting those elements into the DOM using the appendTo() manipulation
methou:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
1.10 Creating, Operating on, and Inserting DOM Elements | 23
jQuery('<p><a>jQuery</a></p>').find('a').attr('href','http://www.jquery.com')
.end().appendTo('body');
</script>
</body>
</html>
Notice how I am using the end() methou heie to unuo the find() methou so that when
I call the appendTo() methou, it appenus what was oiiginally containeu in the initial
wiappei set.
Discussion
In this iecipe we`ve passeu the jQueiy lunction a stiing ol iaw HTML that is taken anu
useu to cieate DOM elements on the lly. It`s also possiLle to simply pass the jQueiy
lunction a DOM oLject cieateu Ly the DOM methou createElement():
jQuery(document.createElement('p')).appendTo('body'); //adds an empty p element
to the page
Ol couise, this coulu Le iathei laLoiious uepenuing upon the specilics ol the usage
when a stiing ol HTML containing multiple elements will woik just line.
It`s also woith mentioning heie that we`ve only sciatcheu the suilace ol the manipu-
lation methous Ly using the appendTo() methou. In auuition to the appendTo() methou,
theie aie also the lollowing manipulation methous:
append()
prepend()
prependTo()
after()
before()
insertAfter()
insertBefore()
wrap()
wrapAll()
wrapInner()
1.11 Removing DOM Elements
Problem
You want to iemove elements liom the DOM.
24 | Chapter 1:jQuery Basics
Solution
The remove() methou can Le useu to iemove a selecteu set ol elements anu theii chiluien
elements liom the DOM. Examine the lollowing coue:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h3>Anchors</h3>
<a href='#'>Anchor Element</a>
<a href='#'>Anchor Element</a>
<a href='#'>Anchor Element</a>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
jQuery('a').remove();
</script>
</body>
</html>
Vhen the pieceuing coue is loaueu into a Liowsei, the anchoi elements will iemain in
the page until the ]avaSciipt is executeu. Once the remove() methou is useu to iemove
all anchoi elements liom the DOM, the page will visually contain only an <h3> element.
It`s also possiLle to pass the methou an expiession to liltei the set ol elements to Le
iemoveu. Foi example, oui coue coulu change to iemove only anchois with a specilic
class:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h3>Anchors</h3>
<a href='#' class='remove'>Anchor Element</a>
<a href='#'>Anchor Element</a>
<a href='#' class="remove">Anchor Element</a>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
jQuery('a').remove('.remove');
</script>
</body>
</html>
Discussion
Vhen using the jQueiy remove() methou, you neeu to keep two things in minu:
1.11 Removing DOM Elements | 25
Vhile the elements selecteu aie iemoveu liom the DOM using remove(), they have
not Leen iemoveu liom the jQueiy wiappei set. That means in theoiy you coulu
continue opeiating on them anu even auu them Lack into the DOM il uesiieu.
This methou will not only iemove the elements liom the DOM, Lut it will also
iemove all event hanuleis anu inteinally cacheu uata that the elements iemoveu
might have containeu.
1.12 Replacing DOM Elements
Problem
You neeu to ieplace DOM noues cuiiently in the DOM with new DOM noues.
Solution
Using the replaceWith() methou, we can select a set ol DOM elements loi ieplacement.
In the lollowing coue example, we use the replaceWith() methou to ieplace all <li>
elements with a class attiiLute ol remove with a new DOM stiuctuie:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<ul>
<li class='remove'>name</li>
<li>name</li>
<li class='remove'>name</li>
<li class='remove'>name</li>
<li>name</li>
<li class='remove'>name</li>
<li>name</li>
<li class='remove'>name</li>
</ul>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
jQuery('li.remove').replaceWith('<li>removed</li>');
</script>
</body>
</html>
The new DOM stiuctuie auueu to the DOM is a stiing paiametei passeu into the
replaceWith() methou. In oui example, all the <li> elements, incluuing chiluien ele-
ments, aie ieplaceu with the new stiuctuie, <li>removed</li>.
26 | Chapter 1:jQuery Basics
Discussion
jQueiy pioviues an inveise to this methou calleu replaceAll() that uoes the same task
with the paiameteis ieveiseu. Foi example, we coulu iewiite the jQueiy coue lounu in
oui iecipe coue like so:
jQuery('<li>removed</li>').replaceAll('li.remove');
Heie we aie passing the jQueiy lunction the HTML stiing anu then using the
replaceAll() methou to select the DOM noue anu its chiluien that we want to Le
iemoveu anu ieplaceu.
1.13 Cloning DOM Elements
Problem
You neeu to clone/copy a poition ol the DOM.
Solution
jQueiy pioviues the clone() methou loi copying DOM elements. Its usage is stiaight-
loiwaiu. Simply select the DOM elements using the jQueiy lunction, anu then call the
clone() methou on the selecteu set ol element(s). The iesult is a copy ol the DOM
stiuctuie Leing ietuineu loi chaining insteau ol the oiiginally selecteu DOM elements.
In the lollowing coue, I am cloning the <ul> element anu then appenuing this copy Lack
into the DOM using the inseiting methou appendTo(). Essentially, I am auuing anothei
<ul> stiuctuie to the page exactly like the one that is alieauy theie:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<ul>
<li>list</li>
<li>list</li>
<li>list</li>
<li>list</li>
</ul>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
jQuery('ul').clone().appendTo('body');
</script>
</body>
</html>
1.13 Cloning DOM Elements | 27
Discussion
The cloning methou is actually veiy hanuy loi moving DOM snippets aiounu insiue ol
the DOM. It`s especially uselul when you want to not only copy anu move the DOM
elements Lut also the events attacheu to the cloneu DOM elements. Closely examine
the HTML anu jQueiy heie:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<ul id="a">
<li>list</li>
<li>list</li>
<li>list</li>
<li>list</li>
</ul>
<ul id="b"></ul>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/JavaScript">
jQuery('ul#a li')
.click(function(){alert('List Item Clicked')})
.parent()
.clone(true)
.find('li')
.appendTo('#b')
.end()
.end()
.remove();
</script>
</body>
</html>
Il you weie to iun this coue in a Liowsei, it woulu clone the <li> elements on the page
that have a click event attacheu to them, inseit these newly cloneu elements (incluuing
events) into the empty <ul>, anu then iemove the <ul> element that we cloneu.
This might stietch a new jQueiy uevelopei`s minu, so let`s examine this jQueiy state-
ment Ly stepping thiough this coue in oiuei to explain the chaineu methous:
1. jQuery('ul#a li') = Select <ul> element with an id attiiLute ol a anu then select
all the <li> elements insiue ol the <ul>.
2. .click(function(){alert('List Item Clicked')}) = Auu a click event to each <li>.
3. .parent() = Tiaveise the DOM, Ly changing my selecteu set to the <ul> element.
+. .clone(true) = Clone the <ul> element anu all its chiluien, incluuing any events
attacheu to the elements that aie Leing cloneu. This is uone Ly passing the
clone() methou a Boolean value ol true.
28 | Chapter 1:jQuery Basics
5. .find('li') = Now, within the cloneu elements, change the set ol elements to only
the <li> elements containeu within the cloneu <ul> element.
6. .appendTo('#b') = Take these selecteu cloneu <li> elements anu place them insiue
ol the <ul> element that has an id attiiLute value ol b.
7. .end() = Retuin to the pievious selecteu set ol elements, which was the cloneu
<ul> element.
S. .end() = Retuin to the pievious selecteu set ol elements, which was the oiiginal
<ul> element we cloneu.
9. .remove() = Remove the oiiginal <ul> element.
Il it`s not oLvious, unueistanuing how to manipulate the selecteu set ol elements oi
ieveit to the pievious selecteu set is ciucial loi complex jQueiy statements.
1.14 Getting, Setting, and Removing DOM Element Attributes
Problem
You have selecteu a DOM element using the jQueiy lunction anu neeu to get oi set the
value ol the DOM element`s attiiLute.
Solution
jQueiy pioviues the attr() methou loi getting anu setting attiiLute values. In the lol-
lowing coue, we aie going to Le setting anu then getting the value ol an <a> element`s
href attiiLute:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<a>jquery.com</a>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js">
</script>
<script type="text/JavaScript">
// alerts the jQuery home page URL
alert(
jQuery('a').attr('href','http://www.jquery.com').attr('href')
);
</script>
</body>
</html>
As you can see in the coue example, we aie selecting the only <a> element in the HTML
uocument, setting its href attiiLute, anu then getting its value with the same attr()
1.14 Getting, Setting, and Removing DOM Element Attributes | 29
methou Ly passing the methou the attiiLute name alone. Hau theie Leen multiple
<a> elements in the uocument, the attr() methou woulu access the liist matcheu ele-
ment. The coue when loaueu into a Liowsei will alert() the value that we set loi the
href attiiLute.
Now, since most elements have moie than one attiiLute availaLle, it`s also possiLle to
set multiple attiiLute values using a single attr() methou. Foi example, we coulu also
set the title attiiLute in the pievious example Ly passing the attr() methou an oLject
insteau ol two stiing paiameteis:
jQuery('a').attr({'href':'http://www.jquery.com','title':'jquery.com'}).attr('href')
Vith the aLility to auu attiiLutes to elements also comes the aLility to iemove attiiLutes
anu theii values. The removeAttr() methou can Le useu to iemove attiiLutes liom
HTML elements. To use this methou, simply pass it a stiing value ol the attiiLute you`u
like to iemove (e.g., jQuery('a')removeAttr('title')).
Discussion
In auuition to the attr() methou, jQueiy pioviues a veiy specilic set ol methous loi
woiking with the HTML element class attiiLute. Since the class attiiLute can contain
seveial values (e.g., class="class1 class2 class3"), these unigue attiiLute methous
aie useu to manage these values.
These jQueiy methous aie as lollows:
addClass()
Upuates the class attiiLute value with a new class/value incluuing any classes that
weie alieauy set
hasClass()
Checks the value ol the class attiiLute loi a specilic class
removeClass()
Removes a unigue class liom the class attiiLute while keeping any values alieauy
set
toggleClass()
Auus the specilieu class il it is not piesent; iemoves the specilieu class il it is piesent
1.15 Getting and Setting HTML Content
Problem
You neeu to get oi set a chunk ol HTML content in the cuiient weL page.
30 | Chapter 1:jQuery Basics
Solution
jQueiy pioviues the html() methou loi getting anu setting chunks (oi DOM stiuctuies)
ol HTML elements. In the lollowing coue, we use this methou to set anu then get the
HTML value ol the <p> element lounu in the HTML uocument:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p></p>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js">
</script>
<script type="text/JavaScript">
jQuery('p').html('<strong>Hello World</strong>, I am a <em><p></em> element.');
alert(jQuery('p').html());
</script>
</body>
</html>
Running this coue in a Liowsei will iesult in a Liowsei aleiting the HTML content
containeu within the <p> element, which we set using the html() methou anu then
ietiieveu using the html() methou.
Discussion
This methou uses the DOM innerHTML piopeity to get anu set chunks ol HTML. You
shoulu also Le awaie that html() is not availaLle on XML uocuments (although it will
woik loi XHTML uocuments).
1.16 Getting and Setting Text Content
Problem
You neeu to get oi set the text that is containeu insiue ol an HTML element(s).
Solution
jQueiy pioviues the text() methou loi getting anu setting the text content ol elements.
In the lollowing coue, we use this methou to set anu then get the text value ol the <p>
element lounu in the HTML uocument:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
1.16 Getting and Setting Text Content | 31
</head>
<body>
<p></p>
<script type="text/JavaScript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js">
</script>
<script type="text/JavaScript">
jQuery('p').text('Hello World, I am a <p> element.');
alert(jQuery('p').text());
</script>
</body>
</html>
Running this coue in a Liowsei will iesult in a Liowsei aleiting the content ol the <p>
element, which we set using the text() methou anu then ietiieveu using the text()
methou.
Discussion
It`s impoitant to iememLei that the text() methou is not unlike html() except that the
text() methou will escape HTML (ieplace < anu > with theii HTML entities). This
means that il you place tags insiue ol the text stiing passeu to the text() methou, it will
conveit these tags to theii HTML entities (< anu >).
1.17 Using the $ Alias Without Creating Global Conflicts
Problem
You want to use the shoitcut $ alias insteau ol typing the gloLal namespace name
(jQueiy) without leai ol gloLal conllicts.
Solution
The solution heie is to cieate an anonymous sell-invoking lunction that we pass the
jQueiy oLject to anu then use the $ chaiactei as a paiametei pointei to the jQueiy
oLject.
Foi example, all jQueiy coue coulu Le encapsulateu insiue the lollowing sell-invoking
lunction:
(function($){ //function to create private scope with $ parameter
//private scope and using $ without worry of conflict
})(jQuery); //invoke nameless function and pass it the jQuery object
Discussion
Essentially, what is going on heie is that we have passeu the gloLal ieleience to jQueiy
to a lunction that cieates a piivate scope. Hau we not uone this anu chosen to use the
shoithanu $ alias in the gloLal scope, we woulu Le taking a iisk Ly assuming that no
32 | Chapter 1:jQuery Basics
othei sciipts incluueu in the HTML uocument (oi sciipts incluueu in the lutuie) use
the $ chaiactei. Vhy iisk it when you can just cieate youi own piivate scope?
Anothei auvantage to uoing this is that coue incluueu insiue ol the anonymous sell-
invoking lunction will iun in its own piivate scope. You can iest assuieu that anything
that is placeu insiue the lunction will likely nevei cause a conllict with othei ]avaSciipt
coue wiitten in the gloLal scope. So, again, why iisk piogiammatic collisions? ]ust
cieate youi own piivate scope.
1.17 Using the $ Alias Without Creating Global Conflicts | 33
CHAPTER 2
Selecting Elements with jQuery
]amcs Padolscy
2.0 Introduction
At the veiy coie ol jQueiy is its selectoi engine, allowing you to select elements within
any uocument Laseu on names, attiiLutes, states, anu moie. Because ol CSS`s popu-
laiity, it maue sense to auopt its selectoi syntax to make it simple to select elements in
jQueiy. As well as suppoiting most ol the selectois specilieu in the CSS 13 specilica-
tions, jQueiy auus guite a lew custon sc|cctors that can Le useu to select elements Laseu
on special states anu chaiacteiistics. Auuitionally, you can cieate youi own custom
selectois! This chaptei uiscusses some ol the moie common pioLlems encounteieu
while selecting elements with jQueiy.
Beloie the liist iecipe, let`s uiscuss a lew Lasic piinciples.
The easiest way to taiget a specilic element oi a set ol elements within a uocument is
Ly using a CSS selectoi within the jQueiy wiappei lunction, like so:
jQuery('#content p a');
// Select all anchor elements within all paragraph elements within #content
Now that we`ve selecteu the elements we`ie altei, we can iun any ol jQueiy`s methous
on that collection. Foi example, auuing a class ol selected to all links is as simple as:
jQuery('#content p a').addClass('selected');
jQueiy olleis many DOM tiaveisal methous to aiu in the element selection piocess,
such as next(), prev(), anu parent(). These anu othei methous accept a selectoi ex-
piession as theii only paiametei, which lilteis the ietuineu iesults accoiuingly. So, you
can use CSS selectois in a numLei ol places, not just within jQuery(...).
Vhen constiucting selectois, theie`s one geneial iule loi optimization: Le only as spe-
cilic as you neeu to Le. It`s impoitant to iememLei that the moie complicateu a selectoi
is, the moie time it will take jQueiy to piocess the stiing. jQueiy uses native DOM
methous to ietiieve the elements you`ie altei. The lact that you can use selectois is only
a piouuct ol a nicely polisheu aLstiaction; theie`s nothing wiong with this, Lut it is
35
veiy impoitant to unueistanu the iamilications ol what you`ie wiiting. Heie is a typical
example ol an unnecessaiily complicateu selectoi:
jQuery('body div#wrapper div#content');
A highei uegiee ol specilicity uoes not necessaiily mean it`s lastei. The pievious selectoi
can Le iewiitten to this:
jQuery('#content');
This has the same ellect Lut manages to shave oll the oveiheau ol the pievious veision.
Also note that sometimes you can luithei optimize Ly specilying a context loi youi
selectois; this will Le uiscusseu latei in the chaptei (see Recipe 2.11).
2.1 Selecting Child Elements Only
Problem
You neeu to select one oi moie uiiect chiluien ol a paiticulai element.
Solution
Use the dircct dcsccndant comLinatoi (>). This comLinatoi expects two selectoi ex-
piessions, one on eithei siue. Foi example, il you want to select all anchoi elements
that iesiue uiiectly Leneath list items, you coulu use this selectoi: li > a. This woulu
select all anchois that aie chiluien ol a list item; in othei woius, all anchois that exist
uiiectly Leneath list items. Heie`s an example:
<a href="/category">Category</a>
<ul id="nav">
<li><a href="#anchor1">Anchor 1</a></li>
<li><a href="#anchor2">Anchor 2</a></li>
<li><span><a href="#anchor3">Anchor 3</a></span></li>
</ul>
Now, to select only the anchois within each list item, you woulu call jQueiy like so:
jQuery('#nav li > a');
// This selects two elements, as expected
The thiiu anchoi within the #nav list is not selecteu Lecause it`s not a chilu ol a list item;
it`s a chilu ol a <span> element.
Discussion
It`s impoitant to uistinguish Letween a chilu anu a uescenuant. A dcsccndant is any
element existing within anothei element, wheieas a chi|d is a uiiect uescenuant; the
analogy ol chiluien anu paients helps massively since the DOM`s hieiaichy is laigely
similai to that.
36 | Chapter 2:Selecting Elements with jQuery
It`s woith noting that comLinatois like > can Le useu without an expiession on the lelt
siue il a context is alieauy specilieu:
jQuery('> p', '#content');
// Fundamentally the same as jQuery('#content > p')
Selecting chiluien in a moie piogiammatic enviionment shoulu Le uone using jQueiy`s
children() methou, to which you can pass a selectoi to liltei the ietuineu elements.
This woulu select all uiiect chiluien ol the #content element:
jQuery('#content').children();
The pieceuing coue is essentially the same as jQuery('#content > *') with one impoi-
tant uilleience; it`s lastei. Insteau ol paising youi selectoi, jQueiy knows what you
want immeuiately. The lact that it`s lastei is not a uselul uilleiential, though. Plus, in
some situations, the speeu uilleience is maiginal veiging on iiielevant, uepenuing on
the Liowsei anu what you`ie tiying to select. Using the children() methou is especially
uselul when you`ie uealing with jQueiy oLjects stoieu unuei vaiiaLles. Foi example:
var anchors = jQuery('a');
// Getting all direct children of all anchor elements
// can be achieved in three ways:
// #1
anchors.children();
// #2
jQuery('> *', anchors);
// #3
anchors.find('> *');
In lact, theie aie even moie ways ol achieving it! In this situation, the liist methou is
the lastest. As stateu eailiei, you can pass a selectoi expiession to the children() meth-
ou to liltei the iesults:
jQuery('#content').children('p');
Only paiagiaph elements that aie uiiect chiluien ol #content will Le ietuineu.
2.2 Selecting Specific Siblings
Problem
You neeu to select only a specilic set ol siLlings ol a paiticulai element.
Solution
Il you`ie looking to select the aujacent siLling ol a paiticulai element, then you can use
the adjaccnt sib|ing comLinatoi (+). Similai to the chilu (>) comLinatoi, the siLling
comLinatoi expects a selectoi expiession on each siue. The iighthanu expiession is the
2.2 Selecting Specific Siblings | 37
suLject ol the selectoi, anu the lelthanu expiession is the siLling you want to match.
Heie`s some example HTML maikup:
<div id="content">
<h1>Main title</h1>
<h2>Section title</h2>
<p>Some content...</p>
<h2>Section title</h2>
<p>More content...</p>
</div>
Il you want to select only <h2> elements that immeuiately lollow <h1> elements, you
can use the lollowing selectoi:
jQuery('h1 + h2');
// Selects ALL H2 elements that are adjacent siblings of H1 elements
In this example, only one <h2> element will Le selecteu (the liist one). The seconu one
is not selecteu Lecause, while it is a siLling, it is not an adjaccnt siLling ol the <h1>
element.
Il, on the othei hanu, you want to select anu liltei all siLlings ol an element, aujacent
oi not, then you can use jQueiy`s siblings() methou to taiget them, anu you can pass
an optional selectoi expiession to liltei the selection:
jQuery('h1').siblings('h2,h3,p');
// Selects all H2, H3, and P elements that are siblings of H1 elements.
Sometimes you`ll want to taiget siLlings uepenuent on theii position ielative to othei
elements; loi example, heie`s some typical HTML maikup:
<ul>
<li>First item</li>
<li class="selected">Second item</li>
<li>Third item</li>
<li>Fourth item</li>
<li>Fifth item</li>
</ul>
To select all list items Leyonu the seconu (altei li.selected), you coulu use the lol-
lowing methou:
jQuery('li.selected').nextAll('li');
The nextAll() methou, just like siblings(), accepts a selectoi expiession to liltei the
selection Leloie it`s ietuineu. Il you uon`t pass a selectoi, then nextAll() will ietuin all
siLlings ol the suLject element that exist altei the suLject element, although not
Leloie it.
Vith the pieceuing example, you coulu also use anothei CSS comLinatoi to select all
list items Leyonu the seconu. The gcncra| sib|ing comLinatoi (~) was auueu in CSS3,
so you pioLaLly haven`t Leen aLle to use it in youi actual style sheets yet, Lut loitunately
you can use it in jQueiy without woiiying aLout suppoit, oi lack theieol. It woiks in
exactly the same lashion as the aujacent siLling comLinatoi (-) except that it selects
38 | Chapter 2:Selecting Elements with jQuery
a|| siLlings that lollow, not just the aujacent one. Using the pieviously specilieu maikup,
you woulu select all list items altei li.selected with the lollowing selectoi:
jQuery('li.selected ~ li');
Discussion
The aujacent siLling comLinatoi can Le conceptually tiicky to use Lecause it uoesn`t
lollow the top-uown hieiaichical appioach ol most othei selectoi expiessions. Still, it`s
woith knowing aLout anu is ceitainly a uselul way ol selecting what you want with
minimal hassle.
The same lunctionality might Le achieveu without a selectoi, in the lollowing way:
jQuery('h1').next('h2');
The next() methou can make a nice alteinative to the selectoi syntax, especially in
a piogiammatic setting when you`ie uealing with jQueiy oLjects as vaiiaLles, loi
example:
var topHeaders = jQuery('h1');
topHeaders.next('h2').css('margin','0');
2.3 Selecting Elements by Index Order
Problem
You neeu to select elements Laseu on theii oiuei among othei elements.
Solution
Depenuing on what you want to uo, you have the lollowing lilteis at youi uisposal.
These may look like CSS pseuuoclasses, Lut in jQueiy they`ie calleu ji|tcrs:
:first
Matches the liist selecteu element
:last
Matches the last selecteu element
:even
Matches even elements (zeio-inuexeu)
:odd
Matches ouu elements (zeio-inuexeu)
:eq(n)
Matches a single element Ly its inuex (n)
:lt(n)
Matches all elements with an inuex Lelow n
2.3 Selecting Elements by Index Order | 39
:gt(n)
Matches all elements with an inuex aLove n
Assuming the lollowing HTML maikup:
<ol>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
<li>Fourth item</li>
</ol>
the liist item in the list coulu Le selecteu in a numLei ol uilleient ways:
jQuery('ol li:first');
jQuery('ol li:eq(0)');
jQuery('ol li:lt(1)');
Notice that Loth the eq() anu lt() lilteis accept a numLei; since it`s zeio-inuexeu, the
liist item is 0, the seconu is 1, etc.
A common ieguiiement is to have alteinating styles on taLle iows; this can Le achieveu
with the :even anu :odd lilteis:
<table>
<tr><td>0</td><td>even</td></tr>
<tr><td>1</td><td>odd</td></tr>
<tr><td>2</td><td>even</td></tr>
<tr><td>3</td><td>odd</td></tr>
<tr><td>4</td><td>even</td></tr>
</table>
You can apply a uilleient class uepenuent on the inuex ol each taLle iow:
jQuery('tr:even').addClass('even');
You`u have to specily the coiiesponuing class (even) in youi CSS style sheet:
table tr.even {
background: #CCC;
}
This coue woulu piouuce the ellect shown in Figuie 2-1.
Iigurc 2-1. Tab|c with cvcn rows dar|cncd
40 | Chapter 2:Selecting Elements with jQuery
Discussion
As mentioneu, an element`s inuex is zeio-Laseu, so il an element is the liist one, then
its inuex is zeio. Apait liom that lact, using the pieceuing lilteis is veiy simple. Anothei
thing to note is that these lilteis ieguiie a collection to match against; the inuex can Le
ueteimineu only il an initial collection is specilieu. So, this selectoi woulun`t woik:
jQuery(':even');
Actually, this selectoi uoes woik, Lut only Lecause jQueiy uoes some
coiiective postpiocessing ol youi selectoi Lehinu the scenes. Il no initial
collection is specilieu, then jQueiy will assume you meant all elements
within the uocument. So, the selectoi woulu actually woik, since it`s
ellectively iuentical to this: jQuery('*:even').
An initial collection is ieguiieu on the lelthanu siue ol the liltei, i.e., something to apply
the liltei to. The collection can Le within an alieauy instantiateu jQueiy oLject, as
shown heie:
jQuery('ul li').filter(':first');
The liltei methou is Leing iun on an alieauy instantiateu jQueiy oLject (containing the
list items).
2.4 Selecting Elements That Are Currently Animating
Problem
You neeu to select elements Laseu on whethei they`ie animating.
Solution
jQueiy olleis a convenient liltei loi this veiy puipose. The :animated liltei will match
only elements that aie cuiiently animating:
jQuery('div:animated');
This selectoi woulu select all <div> elements cuiiently animating. Ellectively, jQueiy
is selecting all elements that have a nonempty animation gueue.
Discussion
This liltei is especially uselul when you neeu to apply a Llanket lunction to all elements
that aie not cuiiently animateu. Foi example, to Legin animating all <div> elements
that aie not alieauy animating, it`s as simple as this:
jQuery('div:not(div:animated)').animate({height:100});
2.4 Selecting Elements That Are Currently Animating | 41
Sometimes you might want to check whethei an element is animating. This can Le uone
with jQueiy`s uselul is() methou:
var myElem = jQuery('#elem');
if( myElem.is(':animated') ) {
// Do something.
}
2.5 Selecting Elements Based on What They Contain
Problem
You neeu to select an element Laseu on what it contains.
Solution
Theie aie noimally only two things you woulu want to gueiy in this iespect: the text
contents anu the element contents (othei elements). Foi the loimei, you can use
the :contains() liltei:
<!-- HTML -->
<span>Hello Bob!</span>
// Select all SPANs with 'Bob' in:
jQuery('span:contains("Bob")');
Note that it`s case sensitive, so this selectoi woulun`t match anything il we seaicheu
loi bob (with a loweicase b). Also, guotes aie not ieguiieu in all situations, Lut it`s a
goou piactice just in case you encountei a situation wheie they aie ieguiieu (e.g., when
you want to use paientheses).
To test loi nesteu elements, you can use the :has() liltei. You can pass any valiu selectoi
to this liltei:
jQuery('div:has(p a)');
This selectoi woulu match all <div> elements that encapsulate <a> elements (anchois)
within <p> elements (paiagiaphs).
Discussion
The :contains() liltei might not lit youi ieguiiements. You may neeu moie contiol
ovei what text to allow anu what to uisallow. Il you neeu that contiol, I suggest using
a iegulai expiession anu testing against the text ol the element, like so:
jQuery('p').filter(function(){
return /(^|\s)(apple|orange|lemon)(\s|$)/.test(jQuery(this).text());
});
This woulu select all paiagiaphs containing the woiu app|c, orangc, oi |cnon. To ieau
moie aLout jQueiy`s filter() methou, have a look at Recipe 2.10.
42 | Chapter 2:Selecting Elements with jQuery
2.6 Selecting Elements by What They Dont Match
Problem
You neeu to select a numLei ol elements that uon`t match a specilic selectoi.
Solution
Foi this, jQueiy gives us the :not liltei, which you can use in the lollowing way:
jQuery('div:not(#content)'); // Select all DIV elements except #content
This liltei will iemove any elements liom the cuiient collection that aie matcheu Ly
the passeu selectoi. The selectoi can Le as complex as you like; it uoesn`t have to Le a
simple expiession, e.g.:
jQuery('a:not(div.important a, a.nav)');
// Selects anchors that do not reside within 'div.important' or have the class 'nav'
Passing complex selectois to the :not liltei is possiLle only in jQueiy
veision 1.3 anu Leyonu. In veisions pievious to that, only simple selectoi
expiessions weie acceptaLle.
Discussion
In auuition to the mentioneu :not liltei, jQueiy also supplies a methou with veiy similai
lunctionality. This methou accepts Loth selectois anu DOM collections/noues. Heie`s
an example:
var $anchors = jQuery('a');
$anchors.click(function(){
$anchors.not(this).addClass('not-clicked');
});
Accoiuing to this coue, when an anchoi is clickeu, all anchois apait liom that one will
have the class not-clicked auueu. The this keywoiu ieleis to the clickeu element.
The not() methou also accepts selectois:
$('#nav a').not('a.active');
This coue selects all anchois iesiuing within #nav that uo not have a class ol active.
2.7 Selecting Elements Based on Their Visibility
Problem
You neeu to select an element Laseu on whethei it`s visiLle.
2.7 Selecting Elements Based on Their Visibility | 43
Solution
You can use eithei the :hidden oi :visible liltei as necessaiy:
jQuery('div:hidden');
Heie aie some othei examples ol usage:
if (jQuery('#elem').is(':hidden')) {
// Do something conditionally
}
jQuery('p:visible').hide(); // Hiding only elements that are currently visible
Discussion
Since jQueiy 1.3.2, these lilteis have uiamatically changeu. Beloie 1.3.2
Loth lilteis woulu iesponu like you woulu expect loi the CSS
visibility piopeity, Lut that is no longei taken into account. Insteau,
jQueiy tests loi the height anu wiuth ol the element in guestion (ielative
to its offsetParent). Il eithei ol these uimensions is zeio, then the ele-
ment is consiueieu hiuuen; otheiwise, it`s consiueieu visiLle.
Il you neeu moie contiol, you can always use jQueiy`s filter() methou, which allows
you to test the element in any way you want. Foi example, you may want to select all
elements that aie set to display:none Lut not those that aie set to visibility:hidden.
Using the :hidden liltei won`t woik Lecause it matches elements with eithei ol those
chaiacteiistics (< v1.3.2) oi uoesn`t take eithei piopeity into consiueiation at all
(>= v1.3.2):
jQuery('*').filter(function(){
return jQuery(this).css('display') === 'none'
&& jQuery(this).css('visibility') !== 'hidden';
});
The pieceuing coue shoulu leave you with a collection ol elements that aie set to
display:none Lut not visibility:hidden. Note that, usually, such a selection won`t Le
necessaiythe :hidden liltei is peilectly suitaLle in most situations.
2.8 Selecting Elements Based on Attributes
Problem
You neeu to select elements Laseu on attiiLutes anu those attiiLutes` values.
Solution
Use an attiiLute selectoi to match specilic attiiLutes anu coiiesponuing values:
jQuery('a[href="http://google.com"]');
44 | Chapter 2:Selecting Elements with jQuery
The pieceuing selectoi woulu select all anchoi elements with an href attiiLute egual
to the value specilieu (http://google.com).
Theie aie a numLei ol ways you can make use ol the attiiLute selectoi:
[attr]
Matches elements that have the specilieu attiiLute
[attr=val]
Matches elements that have the specilieu attiiLute with a ceitain value
[attr!=val]
Matches elements that uon`t have the specilieu attiiLute oi value
[attr^=val]
Matches elements with the specilieu attiiLute anu that stait with a ceitain value
[attr$=val]
Matches elements that have the specilieu attiiLute anu that enu with a ceitain value
[attr~=val]
Matches elements that contain the specilieu value with spaces, on eithei siue (i.e.,
car matches car Lut not cart)
Piioi to jQueiy 1.2 you hau to use XPath syntax (i.e., putting an @ sign
Leloie an attiiLute name). This is now uepiecateu.
You can also comLine multiple attiiLute selectois:
// Select all elements with a TITLE and HREF:
jQuery('*[title][href]');
Discussion
As always, loi special ieguiiements it may Le moie suitaLle to use the filter() methou
to moie specilically outline what you`ie looking loi:
jQuery('a').filter(function(){
return (new RegExp('http:\/\/(?!' + location.hostname + ')')).test(this.href);
});
In this liltei, a iegulai expiession is Leing useu to test the href attiiLute ol each anchoi.
It selects all exteinal links within any page.
The attiiLute selectoi is especially uselul loi selecting elements Laseu on slightly vaiying
attiiLutes. Foi example, il we hau the lollowing HTML:
<div id="content-sec-1">...</div>
<div id="content-sec-2">...</div>
<div id="content-sec-3">...</div>
<div id="content-sec-4">...</div>
2.8 Selecting Elements Based on Attributes | 45
we coulu use the lollowing selectoi to match all ol the <div> elements:
jQuery('div[id^="content-sec-"]');
2.9 Selecting Form Elements by Type
Problem
You neeu to select loim elements Laseu on theii types (hidden, text, checkbox, etc.).
Solution
jQueiy gives us a Lunch ol uselul lilteis loi this veiy puipose, as shown in TaLle 2-1.
Tab|c 2-1. jQucry jorn ji|tcrs
jQuery selector syntax Selects what?
:text <input type="text" />
:password <input type="password" />
:radio <input type="radio" />
:checkbox <input type="checkbox" />
:submit <input type="submit" />
:image <input type="image" />
:reset <input type="reset" />
:button <input type="button" />
:file <input type="file" />
:hidden <input type="hidden" />
So, as an example, il you neeueu to select all text inputs, you woulu simply uo this:
jQuery(':text');
Theie is also an :input liltei that selects all input, textarea, button, anu select
elements.
Discussion
Note that the :hidden liltei, as uiscusseu eailiei, uoes not test loi the type hidden; it
woiks Ly checking the computeu height ol the element. This woiks with input elements
ol the type hidden Lecause they, like othei hiuuen elements, have an offsetHeight
ol zeio.
As with all selectois, you can mix anu match as uesiieu:
jQuery(':input:not(:hidden)');
// Selects all input elements except those that are hidden.
46 | Chapter 2:Selecting Elements with jQuery
These lilteis can also Le useu with iegulai CSS syntax. Foi example, selecting all text
input elements plus all <textarea> elements can Le uone in the lollowing way:
jQuery(':text, textarea');
2.10 Selecting an Element with Specific Characteristics
Problem
You neeu to select an element Laseu not only on its ielationship to othei elements oi
simple attiiLute values Lut also on vaiying chaiacteiistics such as piogiammatic states
not expiessiLle as selectoi expiessions.
Solution
Il you`ie looking loi an element with veiy specilic chaiacteiistics, selectoi expiessions
may not Le the Lest tool. Using jQueiy`s DOM lilteiing methou (filter()), you can
select elements Laseu on anything expiessiLle within a lunction.
The liltei methou in jQueiy allows you to pass eithei a stiing (i.e., a selectoi expiession)
oi a lunction. Il you pass a lunction, then its ietuin value will ueline whethei ceitain
elements aie selecteu. The lunction you pass is iun against eveiy element in the cuiient
selection; eveiy time the lunction ietuins lalse, the coiiesponuing element is iemoveu
liom the collection, anu eveiy time you ietuin tiue, the coiiesponuing element is not
allecteu (i.e., it iemains in the collection):
jQuery('*').filter(function(){
return !!jQuery(this).css('backgroundImage');
});
The pieceuing coue selects all elements with a Lackgiounu image.
The initial collection is ol all elements (*); then the filter() methou is calleu with a
lunction. This lunction will ietuin tiue when a backgroundImage is specilieu loi the
element in guestion. The !! that you see is a guick way ol conveiting any type in ]ava-
Sciipt to its Boolean expiession. Things that evaluate to lalse incluue an empty stiing,
the numLei zeio, the value undefined, the null type, anu, ol couise, the lalse Boolean
itsell. Il any ol these things aie ietuineu liom gueiying the backgroundImage, the lunc-
tion will ietuin lalse, thus iemoving any elements without Lackgiounu images liom
the collection. Most ol what I just saiu is not unigue to jQueiy; it`s just ]avaSciipt
lunuamentals.
In lact, the !! is not necessaiy Lecause jQueiy evaluates the ietuin value into a Boolean
itsell, Lut keeping it theie is still a goou iuea; anyone looking at youi coue can Le
aLsolutely suie ol what you intenueu (it aius ieauaLility).
2.10 Selecting an Element with Specific Characteristics | 47
Vithin the lunction you pass to filter(), you can ielei to the cuiient element via the
this keywoiu. To make it into a jQueiy oLject (so you can access anu peiloim jQueiy
methous), simply wiap it in the jQueiy lunction:
this; // Regular element object
jQuery(this); // jQuery object
Heie aie some othei lilteiing examples to spaik youi imagination:
// Select all DIV elements with a width between 100px and 200px:
jQuery('div').filter(function(){
var width = jQuery(this).width();
return width > 100 && width < 200;
});
// Select all images with a common image extension:
jQuery('img').filter(function(){
return /\.(jpe?g|png|bmp|gif)(\?.+)?$/.test(this.src);
});
// Select all elements that have either 10 or 20 children:
jQuery('*').filter(function(){
var children = jQuery(this).children().length;
return children === 10 || children === 20;
});
Discussion
Theie will always Le seveial uilleient ways to uo something; this is no less tiue when
selecting elements with jQueiy. The key uilleiential is usually going to Le speeu; some
ways aie last, otheis aie slow. Vhen you use a complicateu selectoi, you shoulu Le
thinking aLout how much piocessing jQueiy has to uo in the Lackgiounu. A longei
anu moie complex selectoi will take longei to ietuin iesults. jQueiy`s native methous
can sometimes Le much lastei than using a single selectoi, plus theie`s the auueu Lenelit
ol ieauaLility. Compaie these two technigues:
jQuery('div a:not([href^=http://]), p a:not([href^=http://])');
jQuery('div, p').find('a').not('[href^=http://]');
The seconu technigue is shoitei anu much moie ieauaLle than the liist. Testing in
Fiielox (v3) anu Salaii (v+) ieveals that it`s also lastei than the liist technigue.
2.11 Using the Context Parameter
Problem
You`ve heaiu ol the context paiametei Lut have yet to encountei a situation wheie it`s
uselul.
48 | Chapter 2:Selecting Elements with jQuery
Solution
As well as passing a selectoi expiession to jQuery() oi $(), you can pass a seconu
aigument that specilies the context. The context is wheie jQueiy will seaich loi the
elements matcheu Ly youi selectoi expiession.
The context paiametei is pioLaLly one ol the most unueiuseu ol jQueiy`s leatuies. The
way to use it is incieuiLly simple: pass a selectoi expiession, a jQueiy oLject, a DOM
collection, oi a DOM noue to the context aigument, anu jQueiy will seaich only loi
elements within that context.
Heie`s an example: you want to select all input lielus within a loim Leloie it`s
suLmitteu:
jQuery('form').bind('submit', function(){
var allInputs = jQuery('input', this);
// Now you would do something with 'allInputs'
});
Notice that this was passeu as the seconu aigument; within the hanulei just shown,
this ieleis to the loim element. Since it`s set as the context, jQueiy will only ietuin
input elements within that loim. Il we uiun`t incluue that seconu aigument, then all ol
the uocument`s input elements woulu Le selecteunot what we want.
As mentioneu, you can also pass a iegulai selectoi as the context:
jQuery('p', '#content');
The pieceuing coue ietuins exactly the same collection as the lollowing selectoi:
jQuery('#content p');
Specilying a context can aiu in ieauaLility anu speeu. It`s a uselul leatuie to know aLout!
Discussion
The uelault context useu Ly jQueiy is document, i.e., the topmost item in the DOM
hieiaichy. Only specily a context il it`s uilleient liom this uelault. Using a context can
Le expiesseu in the lollowing way:
jQuery( context ).find( selector );
In lact, this is exactly what jQueiy uoes Lehinu the scenes.
Consiueiing this, il you alieauy have a ieleience to the context, then you shoulu pass
that insteau ol a selectoitheie`s no point in making jQueiy go thiough the selection
piocess again.
2.11 Using the Context Parameter | 49
2.12 Creating a Custom Filter Selector
Problem
You neeu a ieusaLle liltei to taiget specilic elements Laseu on theii chaiacteiistics. You
want something that is succinct anu can Le incluueu within youi selectoi expiessions.
Solution
You can extenu jQueiy`s selectoi expiessions unuei the jQuery.expr[':'] oLject; this
is an alias loi Sizzle.selectors.filters. Each new liltei expiession is uelineu as a
piopeity ol this oLject, like so:
jQuery.expr[':'].newFilter = function(elem, index, match){
return true; // Return true/false like you would on the filter() method
};
The lunction will Le iun on all elements in the cuiient collection anu neeus to ietuin
tiue (to keep the element in the collection) oi lalse (to iemove the element liom the
collection). Thiee Lits ol inloimation aie passeu to this lunction: the element in gues-
tion, the inuex ol this element among the entiie collection, anu a match aiiay ietuineu
liom a iegulai expiession match that contains impoitant inloimation loi the moie
complex expiessions.
Foi example, you might want to taiget all elements that have a ceitain piopeity. This
liltei matches all elements that aie uisplayeu inline:
jQuery.expr[':'].inline = function(elem) {
return jQuery(elem).css('display') === 'inline';
};
Now that we have cieateu a custom selectoi, we can use it in any selectoi expiession:
// E.g. #1
jQuery('div a:inline').css('color', 'red');
// E.g. #2
jQuery('span').filter(':not(:inline)').css('color', 'blue')
jQueiy`s custom selectois (:radio, :hidden, etc.) aie cieateu in this way.
Discussion
As mentioneu, the thiiu paiametei passeu to youi liltei lunction is an aiiay ietuineu
liom a iegulai expiession match that jQueiy peiloims on the selectoi stiing. This match
is especially uselul il you want to cieate a liltei expiession that accepts paranctcrs. Let`s
say that we want to cieate a selectoi that gueiies loi uata helu Ly jQueiy:
jQuery('span').data('something', 123);
// We want to be able to do this:
jQuery('*:data(something,123)');
50 | Chapter 2:Selecting Elements with jQuery
The puipose ol the selectoi woulu Le to select all elements that have hau uata attacheu
to them via jQueiy`s data() methouit specilically taigets elements with a uatakey ol
something, egual to the numLei 123.
The pioposeu liltei (:data) coulu Le cieateu as lollows:
jQuery.expr[':'].data = function(elem, index, m) {
// Remove ":data(" and the trailing ")" from
// the match, as these parts aren't needed:
m[0] = m[0].replace(/:data\(|\)$/g, '');
var regex = new RegExp('([\'"]?)((?:\\\\\\1|.)+?)\\1(,|$)', 'g'),
// Retrieve data key:
key = regex.exec( m[0] )[2],
// Retrieve data value to test against:
val = regex.exec( m[0] );
if (val) {
val = val[2];
}
// If a value was passed then we test for it, otherwise
// we test that the value evaluates to true:
return val ? jQuery(elem).data(key) == val : !!jQuery(elem).data(key);
};
The ieason loi such a complex iegulai expiession is that we want to make it as llexiLle
as possiLle. The new selectoi can Le useu in a numLei ol uilleient ways:
// As we originally mused (above):
jQuery('div:data("something",123)');
// Check if 'something' is a "truthy" value
jQuery('div:data(something)');
// With or without (inner) quotes:
jQuery('div:data(something, "something else")');
Now we have a totally new way ol gueiying uata helu Ly jQueiy on an element.
Il you evei want to auu moie than one new selectoi at the same time, it`s Lest to use
jQueiy`s extend() methou:
jQuery.extend(jQuery.expr[':'], {
newFilter1 : function(elem, index, match){
// Return true or false.
},
newFilter2 : function(elem, index, match){
// Return true or false.
},
newFilter3 : function(elem, index, match){
// Return true or false.
}
});
2.12 Creating a Custom Filter Selector | 51
CHAPTER 3
Beyond the Basics
Ralph Whitbcck
3.0 Introduction
jQueiy is a veiy lightweight liLiaiy that is capaLle ol helping you uo the simple selec-
tions ol DOM elements on youi page. You saw these simple uses in Chaptei 1. In this
chaptei, we`ll exploie how jQueiy can Le useu to manipulate, tiaveise, anu extenu
jQueiy to inlinite possiLilities. As lightweight as jQueiy is, it was Luilt to Le ioLust anu
expanuaLle.
3.1 Looping Through a Set of Selected Results
Problem
You neeu to cieate a list liom youi selecteu set ol DOM elements, Lut peiloiming any
action on the selecteu set is uone on the set as a whole. To Le aLle to cieate a list with
each inuiviuual element, you`ll neeu to peiloim a sepaiate action on each element ol
the selecteu set.
Solution
Let`s say you wanteu to make a list ol eveiy link within a ceitain DOM element (peihaps
it`s a site with a lot ol usei-pioviueu content, anu you wanteu to guickly glance at the
suLmitteu links Leing pioviueu Ly useis). Ve woulu liist cieate oui jQueiy selection,
$("div#post a[href]"), which will select all links with an href attiiLute within the
<div> with the id ol post. Then we want to loop thiough each matcheu element anu
appenu it to an aiiay. See the lollowing coue example:
var urls = [];
$("div#post a[href]").each(function(i) {
urls[i] = $(this).attr('href');
});
53
alert(urls.join(","));
Ve weie aLle to make an aiiay Lecause we iteiateu thiough each element in the jQueiy
oLject Ly using the $().each(); methou. Ve aie aLle to access the inuiviuual elements
anu execute jQueiy methous against those elements Lecause we wiappeu the this
vaiiaLle in a jQueiy wiappei, $(), thus making it a jQueiy oLject.
Discussion
jQueiy pioviues a coie methou that you can use to loop thiough youi set ol selecteu
DOM elements. $().each() is jQueiy`s for loop, which will loop thiough anu pioviue
a sepaiate lunction scope loi each element in the set. $().each(); will iteiate exclusively
thiough jQueiy oLjects.
$().each(); is not the same as the jQueiy utility methou
jQuery.each(object, callback);. The jQuery.each methou is a moie
geneializeu iteiatoi methou that will iteiate thiough Loth oLjects anu
aiiays. See jQueiy`s online uocumentation loi moie inloimation on
jQuery.each() at http://docs.jqucry.con/Uti|itics/jQucry.cach.
In each iteiation, we aie getting the href attiiLute ol the cuiient element liom the main
selection. Ve aie aLle to get the cuiient DOM element Ly using the this keywoiu. Ve
then wiap it in the jQueiy oLject, $(this), so that we can peiloim jQueiy methous/
actions against itin oui case, pulling the href attiiLute liom the DOM element. The
last action is to assign the href attiiLute to a gloLal aiiay, urls.
]ust so we can see what we have, the aiiay URL is joineu togethei with a , anu uisplayeu
to the usei in an aleit Lox. Ve coulu also have auueu the list to an unoiueieu list DOM
element loi uisplay to the usei. Moie piactically, we might want to loimat the list ol
URLs into ]SON loimat anu senu it to the seivei loi piocessing into a uataLase.
Let`s look at anothei example using $().each();. This example is pioLaLly the most
oLvious use ol $().each();. Let`s say we have an unoiueieu list ol names, anu we want
each name to stanu out. One way to accomplish this is to set an alteinate Lackgiounu
coloi loi eveiy othei list item:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Chapter 3 - Recipe 1 - Looping through a set of selected results</title>
<style type="text/css">
.even { background-color: #ffffff; }
.odd { background-color: #cccccc; }
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"
type="text/javascript"></script>
54 | Chapter 3:Beyond the Basics
<script type="text/javascript">
(function($){
$(document).ready(function() {
$("ul > li").each(function(i) {
if (i % 2 == 1)
{
$(this).addClass("odd");
}
else
{
$(this).addClass("even");
}
});
});
})(jQuery);
</script>
</head>
<body>
<h2>Family Members</h2>
<ul>
<li>Ralph</li>
<li>Hope</li>
<li>Brandon</li>
<li>Jordan</li>
<li>Ralphie</li>
</ul>
</body>
</html>
Figuie 3-1 shows the coue output.
Iigurc 3-1. Codc output
As we iteiate thiough each <li> element, we aie testing whethei the cuiient inuex,
which is passeu in as a single aigument to the lunction when executeu, mouueu Ly 2
is egual to 1. Baseu on that conuition, we eithei set one CSS class (.odd) oi anothei CSS
class (.even).
3.1 Looping Through a Set of Selected Results | 55
Even though this may Le the most oLvious way to use $().each(), it
isn`t the most ellicient way to hanule making alteinating Lackgiounu
colois. Ve coulu have accomplisheu this with one line:
$("ul > li:odd").addClass("odd");
All we neeueu to uo was set all the <li> elements to the class .even in
the CSS so that we coulu oveiiiue the ouu <li> elements with the .odd
class with jQueiy.
The Lasic lunction ol $.each(); is to take the matcheu set anu iteiate thiough each
element via ieleience ol the inuex, peiloim some action, anu iteiate to the next element
in the matcheu set until theie aie no moie elements lelt.
3.2 Reducing the Selection Set to a Specified Item
Problem
A jQueiy selectoi is Lioau anu selects all elements on the page Laseu on youi gueiy.
The neeu may iise when you neeu to select a single item, Laseu on its position, Lut
theie isn`t an easy way to select that item without euiting the coue.
Solution
Altei you make youi selection with jQueiy, you can chain the .eq() methou anu pass
in the inuex ol the selection you want to woik with.
The selection inuex is zeio-Laseu, so the liist item in the selection woulu
Le $().eq(0); wheie 0 iepiesents the liist item in the selection. $
().eq(4); iepiesents the lilth item.
Let`s use the enu ol the season stanuings loi the National Hockey League (NHL) con-
leiences as an example ol how we can show which teams maue the playolls anu which
uiun`t. Vhat we neeu to uo is list all the teams in each conleience in the oiuei they
linisheu the season in. Since the top eight teams in each conleience make it to the playoll
iounu, we just neeu to liguie out the eighth entiy in each list anu uiaw a line:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Chapter 3 - Recipe 2 - Reducing the selection set to specified item</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
56 | Chapter 3:Beyond the Basics
<script type="text/javascript">
(function($){
$(document).ready(function(){
$("ol#east > li").eq(7).css("border-bottom", "1px solid #000000");
$("ol#west > li").eq(7).css("border-bottom", "1px solid #000000");
});
})(jQuery);
</script>
</head>
<body>
<h2>Eastern Conference</h2>
<ol id="east">
<li>Boston Bruins</li>
<li>Washington Capitals</li>
<li>New Jersey Devils</li>
<li>Pittsburgh Penguins</li>
<li>Philadelphia Flyers</li>
<li>Carolina Hurricanes</li>
<li>New York Rangers</li>
<li>Montreal Canadians</li>
<li>Florida Panthers</li>
<li>Buffalo Sabres</li>
<li>Ottawa Senators</li>
<li>Toronto Maple Leafs</li>
<li>Atlanta Thrashers</li>
<li>Tampa Bay Lightning</li>
<li>New York Islanders</li>
</ol>
<h2>Western Conference</h2>
<ol id="west">
<li>San Jose Sharks</li>
<li>Detroit Red Wings</li>
<li>Vancouver Canucks</li>
<li>Chicago Blackhawks</li>
<li>Calgary Flames</li>
<li>St. Louis Blues</li>
<li>Columbus Blue Jackets</li>
<li>Anaheim Ducks</li>
<li>Minnesota Wild</li>
<li>Nashville Predators</li>
<li>Edmonton Oilers</li>
<li>Dallas Stars</li>
<li>Phoenix Coyotes</li>
<li>Los Angeles Kings</li>
<li>Colorado Avalanche</li>
</ol>
</body>
</html>
Figuie 3-2 shows the coue output.
3.2 Reducing the Selection Set to a Specified Item | 57
Iigurc 3-2. Codc output
As you can see, we just use an oiueieu list to list the teams in the oiuei they placeu,
then we use jQueiy to auu a Lottom Loiuei to the eighth item in each list. Ve neeu to
auu an ID to each oiueieu list so that we can specily each list in a sepaiate gueiy. Il we
weie to uo $("li").eq(7);, it woulu select only liom the liist list Lecause the gueiy
woulu have counteu all the <li> elements on the page togethei.
58 | Chapter 3:Beyond the Basics
Discussion
The .eq() methou is useu to take a selection set anu ieuuce it to a single item liom that
set. The aigument is the inuex that you want to ieuuce youi selection to. The inuex
staits at 0 anu goes to length -1. Il the aigument is an invaliu inuex, the methou will
ietuin an empty set ol elements insteau ol null.
The .eq() methou is similai to using the $(":eq()"); iight in youi selection, Lut
the .eq() methou allows you to chain to the selection anu line-tune luithei. Foi
example:
$("li").css("background-color","#CCCCCC").eq(0).css("background-color","#ff0000");
This will change the Lackgiounu coloi ol all <li> elements anu then select the liist one
anu give it a uilleient coloi to signily that it is peihaps a heauei item.
3.3 Convert a Selected jQuery Object into a Raw DOM Object
Problem
Selecting elements on a page with jQueiy ietuins a set as a jQueiy oLject anu not as a
iaw DOM oLject. Because it`s a jQueiy oLject, you can only iun jQueiy methous against
the selecteu set. To Le aLle to iun DOM methous anu piopeities against the selecteu
set, the set neeus to Le conveiteu to a iaw DOM oLject.
Solution
jQueiy pioviues a coie methou get(), which will conveit all matcheu jQueiy oLjects
Lack into an aiiay ol DOM oLjects. Auuitionally, you can pass an inuex value in as an
aigument ol get(), which will ietuin the element at the inuex ol the matcheu set as a
DOM oLject, $.get(1);. Now, even though you can get at a single element`s DOM
oLject via $.get(index), it is theie loi histoiical ieasons; the Lest piactices way is to
use the [] notation, $("div")[1];.
Ve aie uiscussing the coie .get() methou, which tiansloims a jQueiy
oLject to a DOM aiiay. Ve aie not uiscussing the Ajax get methou,
which will loau a iemote page using an HTTP GET ieguest.
Because get() ietuins an aiiay, you can tiaveise the aiiay to get at each DOM element.
Once it`s a DOM element, you can then call tiauitional DOM piopeities anu methous
against it. Let`s exploie a simple example ol pulling the innerHTML ol an element:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
3.3 Convert a Selected jQuery Object into a Raw DOM Object | 59
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Chapter 3 - Recipe 3 - Converting a selected jQuery object into a
raw DOM object</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
(function($){
$(document).ready(function(){
var inner = $("div")[0].innerHTML;
alert(inner);
});
})(jQuery);
</script>
</head>
<body>
<div>
<p>
jQuery, the write less, do more JavaScript library. Saving the day
for web developers since 2006.
</p>
</div>
</body>
</html>
Figuie 3-3 shows the output.
Iigurc 3-3. Codc output
Ve stait Ly selecting all the <div> elements on the page anu calling [0]. Ve pass in the
inuex ol the selection we want to woik with; since theie is only one <div> on the page,
we can pass in inuex 0. Finally, we call a piopeity, in this case innerHTML, to ietiieve the
iaw DOM element.
60 | Chapter 3:Beyond the Basics
Discussion
The coie get() methou can Le veiy uselul, as theie aie some non-]avaSciipt methous
that we can utilize loi oui auvantage. Let`s say we have a list anu we neeu to show that
list in ieveise oiuei. Since get() ietuins an aiiay, we can use native aiiay methous to
ieveise soit the list anu then ieuisplay the list:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Chapter 3 - Recipe 3 - Converting a selected jQuery object into a raw DOM
object</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
<!--
(function($){
$(document).ready(function(){
var lis = $("ol li").get().reverse();
$("ol").empty();
$.each(lis, function(i){
$("ol").append("<li>" + lis[i].innerHTML + "</li>");
});
});
})(jQuery);
//-->
</script>
</head>
<body>
<h2>New York Yankees - Batting Line-up</h2>
<ol>
<li>Jeter</li>
<li>Damon</li>
<li>Teixeira</li>
<li>Posada</li>
<li>Swisher</li>
<li>Cano</li>
<li>Cabrera</li>
<li>Molina</li>
<li>Ransom</li>
</ol>
</body>
</html>
Figuie 3-+ shows the output.
3.3 Convert a Selected jQuery Object into a Raw DOM Object | 61
Iigurc 3-1. Codc output
3.4 Getting the Index of an Item in a Selection
Problem
Vhen Linuing an event loi a wiue iange ol selecteu elements on a page, you neeu to
know exactly which item was clickeu liom the selecteu set to peisonalize the action
ol the Lounu event.
Solution
Vhen we click an item, we can use the coie methou index() to seaich thiough a
selection to see what inuex the item is at:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Chapter 3 - Recipe 4 - Getting the index of an item in a selection</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
<!--
(function($){
$(document).ready(function(){
$("div").click(function() {
alert("You clicked on div with an index of " +
$("div").index(this));
62 | Chapter 3:Beyond the Basics
});
});
})(jQuery);
//-->
</script>
</head>
<body>
<div>click me</div>
<div class="test">test</div>
<div>click me</div>
</body>
</html>
Figuie 3-5 shows the output.
Iigurc 3-5. Codc output
Ve stait Ly Linuing all <div> elements to a click event. Then when a <div> is clickeu,
we can liguie out which <div> was clickeu Ly seaiching loi the item in the same selec-
tion: $("div").index(this);, wheie this is the <div> that was clickeu.
3.4 Getting the Index of an Item in a Selection | 63
Discussion
The coie methou index() allows you to get the inuex ol the DOM element you aie
looking loi liom a jQueiy set. As ol jQueiy 1.2.6, you can also pass in the inuex ol a
jQueiy collection to seaich loi. The methou will ietuin the inuex ol the liist occuiience
it linus:
var test = $("div.test");
$("div").each(function(i){
if ($(this).index(test) >= 0)
{
//do something
}
else
{
//do something else
}
});
Ve`ll see whethei the <div> in the loop matches the collection we saveu in the vaiiaLle
test, anu il so, it will peiloim a custom action on the matcheu collection.
Il the inuex methou cannot linu the suLject that was passeu in, it will
ietuin -1.
3.5 Making a Unique Array of Values from an Existing Array
Problem
You have an oiueieu list on youi page. You select all the <li> elements ol that list using
jQueiy; now you neeu to tiansloim that list into anothei list.
Solution
Let`s say we have a list ol people in an oiueieu list. Ve woulu like to uisplay the liist
thiee people liom that oiueieu list as a sentence:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Chapter 3 - Recipe 5 - Making a unique array of values from an existing
array</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
64 | Chapter 3:Beyond the Basics
<!--
(function($){
$(document).ready(function(){
var arr = $.map($("LI"), function(item, index){
while (index < 3)
{
return $(item).html();
}
return null;
});
$(document.body).append("<span>The first three authors are: " +
arr.join(", ") + "</span>");
});
})(jQuery);
//-->
</script>
</head>
<body>
<h1>jQuery Cookbook Authors</h1>
<ol>
<li>John Resig</li>
<li>Cody Lindley</li>
<li>James Padolsey</li>
<li>Ralph Whitbeck</li>
<li>Jonathan Sharp</li>
<li>Michael Geary</li>
<li>Scott Gonzlez</li>
<li>Rebecca Murphey</li>
<li>Remy Sharp</li>
<li>Ariel Flesler</li>
<li>Brian Cherne</li>
<li>Jrn Zaefferer</li>
<li>Mike Hostetler</li>
<li>Nathan Smith</li>
<li>Richard D. Worth</li>
<li>Maggie Wachs</li>
<li>Scott Jehl</li>
<li>Todd Parker</li>
<li>Patty Toland</li>
<li>Rob Burns</li>
</ol>
</body>
</html>
Figuie 3-6 shows the output.
Ve stait Ly making an aiiay ol the <li> elements liom the oiueieu list. Ve will select
all <li> elements on the page Ly using a jQueiy selectoi anu pass that in as an aigument
ol the jQueiy utility methou $.map(), which will take an existing aiiay anu map it
into anothei aiiay. The seconu aigument is the lunction that will iteiate thiough the
aiiay, peiloim tianslations, anu ietuin a new value to Le stoieu into a new aiiay.
3.5 Making a Unique Array of Values from an Existing Array | 65
In the pieceuing example, we iteiate thiough the aiiay we maue, ietuin only the
html() values ol the liist thiee list elements, anu map these values into a new aiiay. Ve
then take that aiiay anu use the join methou to make a single stiing out ol the aiiay
anu inject it into the enu ol the uocument.
Discussion
In the solution, we aie using the jQueiy utility methou $.map(), which will tiansloim
an existing aiiay into anothei aiiay ol items. $.map() takes two aiguments, an aiiay
anu a callLack lunction:
$.map([1,2,3], function(n,i) { return n+i;});
//Output: [1,3,5]
$.map() will iteiate thiough each item ol the oiiginal aiiay anu pass in the item to Le
tianslateu anu the inuex ol the cuiient location within the aiiay. The methou is ex-
pecting a value to Le ietuineu. The ietuineu value will Le inseiteu into the new aiiay.
Il the null value is ietuineu, no value will Le saveu into the new aiiay.
Retuining null Lasically iemoves the item liom the new aiiay.
Iigurc 3-. Codc output
66 | Chapter 3:Beyond the Basics
3.6 Performing an Action on a Subset of the Selected Set
Problem
You neeu to peiloim an action on a set ol tags, Lut theie is no way to isolate these tags
liom all the othei tags on the page in a jQueiy selection set.
Solution
Ve can use the slice() methou to liltei the selection set to a suLset. Ve pass it a staiting
inuex value anu an enuing inuex value, then we can chain oui action at the enu:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Chapter 3 - Recipe 6 - Performing an action on a subset of the selected
set</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
<!--
(function($){
$(document).ready(function(){
$("p").slice(1,3).wrap("<i></i>");
});
})(jQuery);
//-->
</script>
</head>
<body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eget nibh ut
tortor egestas pharetra. Nullam a hendrerit urna. Aenean augue arcu, vestibulum eget
faucibus nec, auctor vel velit. Fusce eget velit non nunc auctor rutrum id et ante.
Donec nec malesuada arcu. Suspendisse eu nibh nulla, congue aliquet metus. Integer
porta dignissim magna, eu facilisis magna luctus ac. Aliquam convallis condimentum
purus, at lacinia nisi semper volutpat. Nulla non risus justo. In ac elit vitae elit
posuere adipiscing.
</p>
<p>
Aliquam gravida metus sit amet orci facilisis eu ultricies risus iaculis. Nunc
tempus tristique magna, molestie adipiscing nibh bibendum vel. Donec sed nisi luctus
sapien scelerisque pretium id eu augue. Mauris ipsum arcu, feugiat non tempor
tincidunt, tincidunt sit amet turpis. Vestibulum scelerisque rutrum luctus. Curabitur
eu ornare nisl. Cras in sem ut eros consequat fringilla nec vitae felis. Nulla
facilisi. Mauris suscipit feugiat odio, a condimentum felis luctus in. Nulla interdum
dictum risus, accumsan dignissim tortor ultricies in. Duis justo mauris, posuere vel
convallis ut, auctor non libero. Ut a diam magna, ut egestas dolor. Nulla convallis,
orci in sodales blandit, lorem augue feugiat nulla, vitae dapibus mi ligula quis
3.6 Performing an Action on a Subset of the Selected Set | 67
ligula. Aenean mattis pulvinar est quis bibendum.
</p>
<p>
Donec posuere pulvinar ligula, nec sagittis lacus pharetra ac. Cras nec
tortor mi. Pellentesque et magna vel erat consequat commodo a id nunc. Donec velit
elit, vulputate nec tristique vitae, scelerisque ac sem. Proin blandit quam ut magna
ultrices porttitor. Fusce rhoncus faucibus tincidunt. Cras ac erat lacus, dictum
elementum urna. Nulla facilisi. Praesent ac neque nulla, in rutrum ipsum. Aenean
imperdiet, turpis sit amet porttitor hendrerit, ante dui eleifend purus, eu fermentum
dolor enim et elit.
</p>
<p>
Suspendisse facilisis molestie hendrerit. Aenean congue congue sapien, ac
luctus nulla rutrum vel. Fusce vitae dui urna. Fusce iaculis mattis justo sit amet
varius. Duis velit massa, varius in congue ut, tristique sit amet lorem. Curabitur
porta, mauris non pretium ultrices, justo elit tristique enim, et elementum tellus
enim sit amet felis. Sed sollicitudin rutrum libero sit amet malesuada. Duis vitae
gravida purus. Proin in nunc at ligula bibendum pharetra sit amet sit amet felis.
Integer ut justo at massa ullamcorper sagittis. Mauris blandit tortor lacus,
convallis iaculis libero. Etiam non pellentesque dolor. Fusce ac facilisis ipsum.
Suspendisse eget ornare ligula. Aliquam erat volutpat. Aliquam in porttitor purus.
</p>
<p>
Suspendisse facilisis euismod purus in dictum. Vivamus ac neque ut sapien
fermentum placerat. Sed malesuada pellentesque tempor. Aenean cursus, metus a
lacinia scelerisque, nulla mi malesuada nisi, eget laoreet massa risus eu felis.
Vivamus imperdiet rutrum convallis. Proin porta, nunc a interdum facilisis, nunc dui
aliquet sapien, non consectetur ipsum nisi et felis. Nullam quis ligula nisi, sed
scelerisque arcu. Nam lorem arcu, mollis ac sodales eget, aliquet ac eros. Duis
hendrerit mi vitae odio convallis eget lobortis nibh sodales. Nunc ut nunc vitae
nibh scelerisque tempor at malesuada sapien. Nullam elementum rutrum odio nec aliquet.
</p>
</body>
</html>
Figuie 3-7 shows the output.
The pieceuing example selects the suLset staiting at inuex 1 anu enuing Leloie inuex
3 anu wiaps an italics tag aiounu the suLselection.
Discussion
The jQueiy methou slice() takes a couple ol options; the liist is the staiting inuex
position, anu the seconu aigument, which is optional, is the enuing inuex position. So,
say you wanteu all <P> tags except the liist one; you coulu uo $("p").slice(1), anu it
woulu stait the selection at the seconu item anu select the iest that is in the jQueiy
selection.
slice() also takes a negative numLei. Il a negative numLei is given, it`ll count in liom
the selection`s enu. So, $("p").slice(1); will select the last item in the selection. Au-
uitionally, $("p").slice(1, 2); will stait the selection at the seconu item anu select
to the seconu-to-last item.
68 | Chapter 3:Beyond the Basics
3.7 Configuring jQuery Not to Conflict with Other Libraries
Problem
Il jQueiy is loaueu on the same page as anothei ]avaSciipt liLiaiy, Loth liLiaiies may
have implementeu the $ vaiiaLle, which iesults in only one ol those methous woiking
coiiectly.
Iigurc 3-7. Codc output
3.7 Configuring jQuery Not to Conflict with Other Libraries | 69
Solution
Let`s say you inheiit a weL page that you neeu to upuate, anu the pievious piogiammei
useu anothei ]avaSciipt liLiaiy like Piototype, Lut you still want to use jQueiy. This
will cause a conllict, anu one ol the two liLiaiies will not woik Laseu on which liLiaiy
is listeu last in the page heau.
Il we just ueclaie Loth jQueiy anu Piototype on the same page like so:
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.3/prototype.js"></script>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
this will cause a ]avaSciipt eiioi: element.dispatchEvent is not a function in
prototype.js. Thanklully, jQueiy pioviues a woikaiounu with the jQuery.noCon
flict() methou:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Chapter 3 - Recipe 7 - Configuring jQuery to free up a conflict with
another library</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.3/prototype.js"></script>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
<!--
jQuery.noConflict();
// Use jQuery via jQuery(...)
jQuery(document).ready(function(){
jQuery("div#jQuery").css("font-weight","bold");
});
// Use Prototype with $(...), etc.
document.observe("dom:loaded", function() {
$('prototype').setStyle({
fontSize: '10px'
});
});
//-->
</script>
</head>
<body>
<div id="jQuery">Hello, I am a jQuery div</div>
<div id="prototype">Hello, I am a Prototype div</div>
</body>
</html>
70 | Chapter 3:Beyond the Basics
Figuie 3-S shows the output.
Iigurc 3-8. Codc output
Vhen you call jQuery.noConflict(), it gives contiol ol the $ vaiiaLle Lack to whomevei
implementeu it liist. Once you liee up the $ vaiiaLle, you only will Le aLle to access
jQueiy with the jQuery vaiiaLle. Foi example, when you useu to use $("div p"), you
woulu now use jQuery("div p").
Discussion
The jQueiy liLiaiy anu viitually all ol its plugins aie constiaineu Ly the jQueiy name-
space. You shoulun`t get a conllict with the jQueiy vaiiaLle anu any othei liLiaiy (i.e.,
Piototype, YUI, etc.). jQueiy uoes howevei use $ as a shoitcut loi the jQueiy oLject.
This shoitcut uelinition is what conllicts with othei liLiaiies that also use the $ vaiiaLle.
As we`ve seen in the solution, we can liee jQueiy ol the $ shoitcut anu ieveit to using
the jQueiy oLject.
Theie is anothei option. Il you want to make suie jQueiy won`t conllict with anothei
liLiaiy Lut still have the Lenelit ol a shoit name, you can call jQuery.noConflict() anu
assign it to a vaiiaLle:
var j = jQuery.noConflict();
j(document).ready(function(){
j("div#jQuery").css("font-weight","bold");
});
You can ueline youi own shoit name Ly choosing the vaiiaLle name you assign,
jQuery.noConflict().
Finally, anothei option is to encapsulate youi jQueiy coue insiue a closuie:
jQuery.noConflict();
(function($){
$("div#jQuery").css("font-weight","bold");
})(jQuery);
By using a closuie, you tempoiaiily make the $ vaiiaLle availaLle to the jQueiy oLject
while Leing iun insiue the lunction. Once the lunction enus, the $ vaiiaLle will ieveit
to the liLiaiy that hau initial contiol.
3.7 Configuring jQuery Not to Conflict with Other Libraries | 71
Il you use this technigue, you will not Le aLle to use othei liLiaiies`
methous within the encapsulateu lunction that expect the $.
3.8 Adding Functionality with Plugins
Problem
The jQueiy liLiaiy is a small, slick, poweilul ]avaSciipt liLiaiy, Lut it uoesn`t come
pieloaueu with eveiy piece ol lunctionality that you may neeu.
Solution
jQueiy was Luilt with extensiLility in minu. Il the coie jQueiy liLiaiy can`t uo what
you want, chances aie a jQueiy plugin authoi has wiitten a plugin that will hanule youi
neeu, pioLaLly in as little as one line ol coue.
To incluue a plugin on youi page, all you neeu to uo is uownloau the plugin .js lile,
incluue the jQueiy liLiaiy on the page, then immeuiately altei, incluue youi plugin on
the page. Then, in eithei anothei .js lile oi in a sciipt Llock on the page, you`ll typically
neeu to call the plugin anu pioviue any options that may Le ieguiieu.
Heie is an example using the jQueiy cycle plugin uevelopeu Ly Mike Alsup:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Chapter 3 - Recipe 8 - Adding Functionality with Plugins</title>
<style type="text/css">
.pics {
height: 232px;
width: 232px;
padding: 0;
margin: 0;
}
.pics img {
padding: 15px;
border: 1px solid #ccc;
background-color: #eee;
width: 200px;
height: 200px;
top: 0;
left: 0
}
</style>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<!--Now include your plugin declarations after you've declared jQuery on the page-->
72 | Chapter 3:Beyond the Basics
<script type="text/javascript" src="scripts/2.8/jquery.cycle.all.min.js?
v2.60"></script>
<script type="text/javascript">
<!--
(function($){
$(document).ready(function(){
$('.pics').cycle('fade');
});
})(jQuery);
//-->
</script>
</head>
<body>
<div class="pics">
<img src="images/2.8/beach1.jpg" width="200" height="200" alt="Beach 1" />
<img src="images/2.8/beach2.jpg" width="200" height="200" alt="Beach 2" />
<img src="images/2.8/beach3.jpg" width="200" height="200" alt="Beach 3" />
</div>
</body>
</html>
Figuie 3-9 shows the output.
Iigurc 3-9. Codc output (onc inagc jading into anothcr)
Vith one line ol coue, we aie aLle to make a sliueshow ellect that will show one image
at a time anu then laue to the next image automatically. The cycle plugin is also ex-
tensiLle Lecause it was wiitten so uevelopeis can pioviue uilleient options to have
uilleient tiansition ellects anu layouts.
Discussion
jQueiy has one ol the laigest communities ol uevelopeis ol any ol the ]avaSciipt liLia-
iies. This laige community contiiLutes to a laige Lase ol plugins anu tutoiials that aie
3.8 Adding Functionality with Plugins | 73
availaLle on the VeL. jQueiy hosts a iepositoiy ol plugins that have Leen wiitten anu
suLmitteu to http://p|ugins.jqucry.con Ly the authois. Theie aie cuiiently moie than
1,600 plugins listeu in the iepositoiy, anu you can linu plugins in many uilleient cat-
egoiies. Plugin authois aie inviteu to suLmit theii plugins anu to give a uesciiption, a
link to the plugin, anu a link to the plugin`s uocumentation. The iepositoiy makes it
easy loi uevelopeis to seaich loi the specilic lunctionality they want.
Chances aie that, as a uevelopei, you will eventually linu a plugin that meets youi
ieguiiements. But on the oll chance that a plugin uoesn`t exist, cieating a plugin youi-
sell is laiily stiaightloiwaiu. Heie aie some points to iememLei:
Name youi lile jqucry.jnanc oj p|uginj.js, as in jqucry.dcbug.js.
All new methous aie attacheu to the jQuery.fn oLject; all lunctions to the jQueiy
oLject.
Insiue methous, this is a ieleience to the cuiient jQueiy oLject.
Any methous oi lunctions you attach must have a semicolon (;) at the enu
otheiwise, the coue will Lieak when compiesseu.
Youi methou must ietuin the jQueiy oLject, unless explicitly noteu otheiwise.
You shoulu use this.each to iteiate ovei the cuiient set ol matcheu elementsit
piouuces clean anu compatiLle coue that way.
Always use jQuery insteau ol $ insiue youi plugin couethat allows useis to change
the alias loi jQueiy in a single place.
Foi moie inloimation anu examples on cieating plugins, you can go to the Authoiing
page on the jQueiy uocumentation site, oi you can skip aheau to Chaptei 12 wheie
Mike Hostetlei will go into moie uetail.
3.9 Determining the Exact Query That Was Used
Problem
Vhile wiiting a plugin oi a methou that extenus jQueiy, you neeu to know exactly
what the selection anu the context useu when calling the methou so that the methou
can Le iecalleu.
Solution
Ve can use the coie piopeities .selector anu .context in conjunction with each othei
so we can ie-cieate the oiiginal gueiy that was passeu thiough. Ve neeu to use Loth
in conjunction Lecause not all gueiies to oui lunction oi plugin will Le within the
uelault uocument context:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
74 | Chapter 3:Beyond the Basics
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Chapter 3 - Recipe 9 - Determining the exact query that was used</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
<!--
(function($){
$.fn.ShowQuery = function(i) {
alert("$(\""+ $(this).selector + "\", " + $(this).context +")");
if (i < 3)
{
$($(this).selector, $(this).context).ShowQuery(i+1);
}
};
$("div").ShowQuery(1);
})(jQuery);
//-->
</script>
</head>
<body>
<div>
This is a div.
</div>
</body>
</html>
Figuie 3-10 shows the output.
Iigurc 3-10. Codc output (a|crt box)
3.9 Determining the Exact Query That Was Used | 75
Discussion
In the pieceuing example, we ueline a methou that can Le calleu liom a jQueiy selec-
tion, ShowQuery. Vithin that methou, we aleit the gueiy as it was passeu in anu then
iecuisively iecall ShowQuery again with the same jQueiy selectoi. The if statement is
theie so that we uon`t get into a iecuisive loop.
The coie piopeities .selector anu .context weie intiouuceu in jQueiy 1.3, which was
ieleaseu in ]anuaiy 2009. These methous aie geaieu moie towaiu plugin uevelopeis
who may neeu to peiloim an action against the oiiginal gueiy passeu in. A potential
use case ol using these methous is to ieiun the selection gueiy oi to check to see whethei
an element is in the selection.
.selector ietuins as a stiing the actual selectoi that was useu to match the given ele-
ments. .selector will ietuin the whole selectoi il, say, the selection is Lioken up wheie
theie is a selectoi anu then the matcheu set is naiioweu with the use ol the find()
methou:
$("div").find("a").selector;
//returns: "div a"
.context will ietuin the DOM noue oiiginally passeu in to jQuery(). Il no context was
set in the selectoi, the context will uelault to the uocument.
76 | Chapter 3:Beyond the Basics
CHAPTER 4
jQuery Utilities
]onathan Sharp
4.0 Introduction
Olten, when thinking anu talking aLout jQueiy, the main concepts that come to minu
aie DOM anu style manipulation anu Lehavioi (events). Yet theie aie also a numLei
ol coie leatuies anu utility lunctions tuckeu away loi the uevelopei`s Lenelit. This
chaptei is locuseu on exposing, uisclosing, anu explaining these not-so-common utility
methous ol jQueiy.
4.1 Detecting Features with jQuery.support
Problem
You neeu to attach a special click hanulei to all anchoi tags that have just a hash loi
the cuiient page, anu you uon`t want to iisk it Lieaking Lecause ol Liowsei suppoit
issues.
Solution
(function($) {
$(document).ready(function() {
$('a')
.filter(function() {
var href = $(this).attr('href');
// Normalize the URL
if ( !jQuery.support.hrefNormalized ) {
var loc = window.location;
href = href.replace( loc.protocol + '//' + loc.host + loc.pathname,
'');
}
// This anchor tag is of the form <a href="#hash">
return ( href.substr(0, 1) == '#' );
})
77
.click(function() {
// Special click handler code
});
});
})(jQuery);
Discussion
The jQuery.support oLject was auueu in veision 1.3 anu contains Boolean llags to help
wiite coue using Liowsei leatuie uetection. In oui example, Inteinet Exploiei (IE) has
a uilleient Lehavioi in how it hanules the href attiiLute. IE will ietuin the lull URL
insteau ol the exact href attiiLute. Using the hrefNormalized attiiLute, we have lutuie-
piooleu oui solution in the event that a latei veision ol IE changes this Lehavioi. Oth-
eiwise, we woulu have neeueu a conuitional that containeu specilic Liowsei veisions.
Vhile it may Le tempting, it is Lest to avoiu this appioach Lecause it ieguiies lutuie
maintenance as new veisions ol Liowseis aie ieleaseu. Anothei ieason to avoiu taiget-
ing specilic Liowseis is that it is possiLle loi clients to intentionally oi unintentionally
iepoit an incoiiect usei agent stiing. In auuition to the hrefNormalized attiiLute, a
numLei ol auuitional attiiLutes exist:
boxModel
Tiue il the Liowsei ienueis accoiuing to the V3C CSS Lox mouel specilication
cssFloat
Tiue il style.cssFloat is useu to get the cuiient CSS lloat value
hrefNormalized
Tiue il the Liowsei leaves intact the iesults liom getAttribute('href')
htmlSerialize
Tiue il the Liowsei piopeily seiializes link elements with the innerHTML attiiLute
leadingWhitespace
Tiue il the Liowsei pieseives leauing whitespace when innerHTML is useu
noCloneEvent
Tiue il the Liowsei uoes not clone event hanuleis when elements aie cloneu
objectAll
Tiue il getElementsByTagName('*') on an element ietuins all uescenuant elements
opacity
Tiue il the Liowsei can inteipiet the CSS opacity style
scriptEval
Tiue il using appendChild loi a <script> tag will execute the sciipt
style
Tiue il getAttribute('style') is aLle to ietuin the inline style specilieu Ly an
element
tbody
Tiue il the Liowsei allows <table> elements without a <tbody> element
78 | Chapter 4:jQuery Utilities
4.2 Iterating Over Arrays and Objects with jQuery.each
Problem
You neeu to iteiate oi loop ovei each element in an aiiay oi attiiLute ol an oLject.
Solution
(function($) {
$(document).ready(function() {
var months = [ 'January', 'February', 'March', 'April', 'May',
'June', 'July', 'August', 'September', 'October',
'November', 'December'];
$.each(months, function(index, value) {
$('#months').append('<li>' + value + '</li>');
});
var days = { Sunday: 0, Monday: 1, Tuesday: 2, Wednesday: 3,
Thursday: 4, Friday: 5, Saturday: 6 };
$.each(days, function(key, value) {
$('#days').append('<li>' + key + ' (' + value + ')</li>');
});
});
})(jQuery);
Discussion
In this iecipe, we iteiate ovei Loth an aiiay anu an oLject using $.each(), which pioviues
an elegant inteilace to the common task ol iteiation. The liist aigument to the
$.each() methou is the aiiay oi oLject to iteiate ovei, with the seconu aigument Leing
the callLack methou that is executeu loi each element. (Note that this is slightly uil-
leient liom the jQueiy collection methou $('div').each(), whose liist aigument is the
callLack lunction.)
Vhen the callLack lunction uelineu Ly the uevelopei is executeu, the this vaiiaLle is
set to the value ol the element cuiiently Leing iteiateu. Thus, the pievious iecipe coulu
Le iewiitten as lollows:
(function($) {
$(document).ready(function() {
var months = [ 'January', 'February', 'March', 'April', 'May',
'June', 'July', 'August', 'September', 'October',
'November', 'December'];
$.each(months, function() {
$('#months').append('<li>' + this + '</li>');
});
var days = { Sunday: 0, Monday: 1, Tuesday: 2, Wednesday: 3,
Thursday: 4, Friday: 5, Saturday: 6 };
$.each(days, function(key) {
$('#days').append('<li>' + key + ' (' + this + ')</li>');
});
4.2 Iterating Over Arrays and Objects with jQuery.each | 79
});
})(jQuery);
4.3 Filtering Arrays with jQuery.grep
Problem
You neeu to liltei anu iemove elements in an aiiay.
Solution
(function($) {
$(document).ready(function() {
var months = [ 'January', 'February', 'March', 'April', 'May',
'June', 'July', 'August', 'September', 'October',
'November', 'December'];
months = $.grep(months, function(value, i) {
return ( value.indexOf('J') == 0 );
});
$('#months').html( '<li>' + months.join('</li><li>') + '</li>' );
});
})(jQuery);
Discussion
This iecipe uses the $.grep() methou to liltei the months aiiay so that it only incluues
entiies that Legin with the capital lettei J. The $.grep methou ietuins the lilteieu aiiay.
The callLack methou uelineu Ly the uevelopei takes two aiguments anu is expecteu to
ietuin a Boolean value ol true to keep an element oi false to have it iemoveu. The liist
aigument specilieu is the value ol the aiiay element (in this case, the month), anu the
seconu aigument passeu in is the inciemental value ol the numLei ol times the
$.grep() methou has loopeu. So, loi example, il you want to iemove eveiy othei month,
you coulu test whethei ( i % 2 ) == 0, which ietuins the iemainuei ol i / 2. (The % is
the mouulus opeiatoi, which ietuins the iemainuei ol a uivision opeiation. So, when
i = 4, i uiviueu Ly 2 has a iemainuei ol 0.)
(function($) {
$(document).ready(function() {
var months = [ 'January', 'February', 'March', 'April', 'May',
'June', 'July', 'August', 'September', 'October',
'November', 'December'];
months = $.grep(months, function(value, i) {
return ( i % 2 ) == 0;
});
$('#months').html( '<li>' + months.join('</li><li>') + '</li>' );
});
})(jQuery);
80 | Chapter 4:jQuery Utilities
4.4 Iterating and Modifying Array Entries with jQuery.map
Problem
You neeu to loop ovei each element in an aiiay anu mouily its value.
Solution
(function($) {
$(document).ready(function() {
var months = [ 'January', 'February', 'March', 'April', 'May',
'June', 'July', 'August', 'September', 'October',
'November', 'December'];
months = $.map(months, function(value, i) {
return value.substr(0, 3);
});
$('#months').html( '<li>' + months.join('</li><li>') + '</li>' );
});
})(jQuery);
Discussion
In this iecipe, $.map() is iteiating ovei the months aiiay anu ietuins the aLLieviation
(liist thiee chaiacteis). The $.map() methou takes an aiiay anu a callLack methou as
aiguments anu iteiates ovei each aiiay element executing the callLack as uelineu Ly
the uevelopei. The aiiay entiy will Le upuateu with the ietuin value ol the callLack.
4.5 Combining Two Arrays with jQuery.merge
Problem
You have two aiiays that you neeu to comLine oi concatenate.
Solution
(function($) {
$(document).ready(function() {
var horseBreeds = ['Quarter Horse', 'Thoroughbred', 'Arabian'];
var draftBreeds = ['Belgian', 'Percheron'];
var breeds = $.merge( horseBreeds, draftBreeds );
$('#horses').html( '<li>' + breeds.join('</li><li>') + '</li>' );
});
})(jQuery);
4.5 Combining Two Arrays with jQuery.merge | 81
Discussion
In this example, we have two aiiays that contain a list ol hoise Lieeus. The aiiays aie
comLineu in the oiuei ol liist - seconu. So, the linal breeds aiiay will look like this:
['Quarter Horse', 'Thoroughbred', 'Arabian', 'Belgian', 'Percheron']
4.6 Filtering Out Duplicate Array Entries with jQuery.unique
Problem
You have two jQueiy DOM collections that neeu to have uuplicate elements iemoveu:
(function($) {
$(document).ready(function() {
var animals = $('li.animals').get();
var horses = $('li.horses').get();
$('#animals')
.append( $(animals).clone() )
.append( $(horses).clone() );
});
})(jQuery);
Solution
(function($) {
$(document).ready(function() {
var animals = $('li.animals').get();
var horses = $('li.horses').get();
var tmp = $.merge( animals, horses );
tmp = $.unique( tmp );
$('#animals').append( $(tmp).clone() );
});
})(jQuery);
Discussion
jQueiy`s $.unique() lunction will iemove uuplicate DOM elements liom an aiiay oi
collection. In the pievious iecipe, we comLine the animals anu horses aiiays using
$.merge(). jQueiy makes use ol $.unique() thioughout most ol its coie anu inteinal
lunctions such as .find() anu .add(). Thus, the most common use case loi this methou
is when opeiating on an aiiay ol elements not constiucteu with jQueiy.
4.7 Testing Callback Functions with jQuery.isFunction
Problem
You have wiitten a plugin anu neeu to test whethei one ol the settings is a valiu callLack
lunction.
82 | Chapter 4:jQuery Utilities
Solution
(function($) {
$.fn.myPlugin = function(settings) {
return this.each(function() {
settings = $.extend({ onShow: null }, settings);
$(this).show();
if ( $.isFunction( settings.onShow ) ) {
settings.onShow.call(this);
}
});
};
$(document).ready(function() {
$('div').myPlugin({
onShow: function() {
alert('My callback!');
}
});
});
})(jQuery);
Discussion
Vhile the ]avaSciipt language pioviues the typeof opeiatoi, inconsistent iesults anu
euge cases acioss weL Liowseis neeu to Le taken into account. jQueiy pioviues
the .isFunction() methou to ease the uevelopei`s joL. Voith pointing out is that since
veision 1.3, this methou woiks loi usei-uelineu lunctions anu ietuins inconsistent ie-
sults with Luilt-in language lunctions such as this:
jQuery.isFunction( document.getElementById );
which ietuins lalse in veisions ol Inteinet Exploiei.
4.8 Removing Whitespace from Strings or Form Values with
jQuery.trim
Problem
You have an input loim anu neeu to iemove the whitespace that a usei may have enteieu
at eithei the Leginning oi enu ol a stiing.
Solution
<input type="text" name="first_name" class="cleanup" />
<input type="text" name="last_name" class="cleanup" />
(function($) {
$(document).ready(function() {
$('input.cleanup').blur(function() {
var value = $.trim( $(this).val() );
$(this).val( value );
4.8 Removing Whitespace from Strings or Form Values with jQuery.trim | 83
});
});
})(jQuery);
Discussion
Upon the usei Lluiiing a lielu, the value as enteieu Ly the usei$(this).val()is
ietiieveu anu passeu thiough the $.trim() methou that stiips all whitespace chaiacteis
(space, taL, anu newline chaiacteis) liom the Leginning anu enu ol the stiing. The
tiimmeu stiing is then set as the value ol the input lielu again.
4.9 Attaching Objects and Data to DOM with jQuery.data
Problem
Given the lollowing DOM coue:
var node = document.getElementById('myId');
node.onclick = function() {
// Click handler
};
node.myObject = {
label: document.getElementById('myLabel')
};
you have metauata associateu with a DOM element loi easy ieleience. Because ol
llaweu gaiLage collection implementations ol some weL Liowseis, the pieceuing coue
can cause memoiy leaks.
Solution
Piopeities auueu to an oLject oi DOM noue at iuntime (calleu cxpandos) exhiLit a
numLei ol issues Lecause ol llaweu gaiLage collection implementations in some weL
Liowseis. jQueiy pioviues uevelopeis with an intuitive anu elegant methou
calleu .data() that aius uevelopeis in avoiuing memoiy leak issues altogethei:
$('#myId').data('myObject', {
label: $('#myLabel')[0]
});
var myObject = $('#myId').data('myObject');
myObject.label;
Discussion
In this iecipe, we use the .data() methou, which manages access to oui uata anu pio-
viues a clean sepaiation ol uata anu maikup.
84 | Chapter 4:jQuery Utilities
One ol the othei Lenelits ol using the data() methou is that it implicitly tiiggeis get
Data anu setData events on the taiget element. So, given the lollowing HTML:
<div id="time" class="updateTime"></div>
we can sepaiate oui conceins (mouel anu view) Ly attaching a hanulei loi the
setData event, which ieceives thiee aiguments (the event oLject, uata key, anu uata
value):
// Listen for new data
$(document).bind('setData', function(evt, key, value) {
if ( key == 'clock' ) {
$('.updateTime').html( value );
}
});
The setData event is then tiiggeieu eveiy time we call .data() on the uocument element:
// Update the 'time' data on any element with the class 'updateTime'
setInterval(function() {
$(document).data('clock', (new Date()).toString() );
}, 1000);
So, in the pievious iecipe, eveiy 1 seconu (1,000 milliseconus) we upuate the clock uata
piopeity on the document oLject, which tiiggeis the setData event Lounu to the
document, which in tuin upuates oui uisplay ol the cuiient time.
4.10 Extending Objects with jQuery.extend
Problem
You have uevelopeu a plugin anu neeu to pioviue uelault options allowing enu useis
to oveiwiite them.
Solution
(function($) {
$.fn.myPlugin = function(options) {
options = $.extend({
message: 'Hello world',
css: {
color: 'red'
}
}, options);
return this.each(function() {
$(this).css(options.css).html(options.message);
});
};
})(jQuery);
4.10 Extending Objects with jQuery.extend | 85
Discussion
In this iecipe, we use the $.extend() methou pioviueu Ly jQueiy. $.extend() will ietuin
a ieleience to the liist oLject passeu in with the lattei oLjects oveiwiiting any piopeities
they ueline. The lollowing coue uemonstiates how this woiks in piactice:
var obj = { hello: 'world' };
obj = $.extend(obj, { hello: 'big world' }, { foo: 'bar' });
alert( obj.hello ); // Alerts 'big world'
alert( obj.foo ); // Alerts 'bar';
This allows loi myPlugin() in oui iecipe to accept an options oLject that will oveiwiite
oui uelault settings. The lollowing coue shows how an enu usei woulu oveiwiite the
uelault CSS color setting:
$('div').myPlugin({ css: { color: 'blue' } });
One special case ol the $.extend() methou is that when given a single oLject, it will
extenu the Lase jQueiy oLject. Thus, we coulu ueline oui plugin as lollows to extenu
the jQueiy coie:
$.fn.extend({
myPlugin: function() {
options = $.extend({
message: 'Hello world',
css: {
color: 'red'
}
}, options);
return this.each(function() {
$(this).css(options.css).html(options.message);
});
}
});
$.extend() also pioviues a lacility loi a ueep (oi iecuisive) copy. This is accomplisheu
Ly passing in Boolean true as the liist paiametei. Heie is an example ol how a ueep
copy woulu woik:
var obj1 = { foo: { bar: '123', baz: '456' }, hello: 'world' };
var obj2 = { foo: { car: '789' } };
var obj3 = $.extend( obj1, obj2 );
Vithout passing in true, obj3 woulu Le as lollows:
{ foo: { car: '789 }, hello: 'world' }
Il we specily a ueep copy, obj3 woulu Le as lollows altei iecuisively copying all
piopeities:
var obj3 = $.extend( true, obj1, obj2 );
// obj3
{ foo: { bar: '123', baz: '456', car: '789 }, hello: 'world' }
86 | Chapter 4:jQuery Utilities
CHAPTER 5
Faster, Simpler, More Fun
Michacl Gcary and Scott Gonzlcz
5.0 Introduction
Neaily eveiy uay, someone asks on the jQueiy Google Gioup how they can make theii
coue simplei oi lastei, oi how to ueLug a piece ol coue that isn`t woiking.
This chaptei will help you simplily youi jQueiy coue, making it easiei to ieau anu moie
lun to woik on. Anu we`ll shaie some tips loi linuing anu lixing those Lugs.
Ve`ll also help you make youi coue iun lastei, anu egually impoitant, linu out which
paits ol youi coue you neeu to speeu up. So youi site`s visitois will have moie lun using
the snappy pages on youi site.
That`s what we call a win-win situation. Happy couing!
5.1 Thats Not jQuery, Its JavaScript!
Problem
You`ie a weL uesignei who is new to jQueiy, anu you`ie having tiouLle with the syntax
ol an if/else statement. You know it must Le a simple pioLlem, anu Leloie asking on
the jQueiy mailing list, you uo youi homewoik: you seaich the jQueiy uocumentation
anu linu nothing. VeL seaiches loi teims like jqucry ij c|sc statcncnt aien`t pioving
helplul eithei.
You also neeu to split an email auuiess into two paits, sepaiating it at the @ sign. You`ve
heaiu that theie is a lunction to split stiings, Lut theie uoesn`t seem to Le any inloi-
mation in the jQueiy uocumentation aLout this eithei.
Is jQueiy ieally that pooily uocumenteu?
87
Solution
The if/else statement anu the .split() methou loi stiings aie pait ol ]avaSciipt, not
pait ol jQueiy.
So, these weL seaiches will tuin up moie uselul iesults:
javascript ij c|sc statcncnt
javascript sp|it string
Discussion
]avaSciipt expeits, please uon`t Lite the newLies.
NewLies, uon`t leel Lau il you`ve sciatcheu youi heau ovei something like this.
Il you`ie an olu pio at ]avaSciipt, you may laugh at these guestions. But they come up
laiily olten on the jQueiy mailing list, anu unueistanuaLly so. jQueiy is uesigneu to
make simple ]avaSciipt couing so easy that someone who`s nevei piogiammeu Leloie
can pick up the Lasics anu auu uselul ellects to a page, without having to leain a ieal
piogiamming language.
But jQueiy is ]avaSciipt. jQueiy itsell is 100 puie ]avaSciipt coue, anu eveiy line ol
jQueiy you wiite is also a line ol ]avaSciipt.
You can inueeu get many simple tasks uone with jQueiy without ieally unueistanuing
its ielationship to ]avaSciipt, Lut the moie you leain aLout the unueilying language,
the moie piouuctiveanu less liustiatingyoui jQueiy expeiience will Le.
5.2 Whats Wrong with $(this)?
Problem
You have an event hanulei that auus a class to a DOM element, waits one seconu using
setTimeout(), anu then iemoves that class:
$(document).ready( function() {
$('.clicky').click( function() {
$(this).addClass('clicked');
setTimeout( function() {
$(this).removeClass('clicked');
}, 1000 );
});
});
The class gets auueu when you click, Lut it nevei gets iemoveu. You have conliimeu
that the coue insiue setTimeout() is Leing calleu, Lut it uoesn`t seem to uo anything.
You`ve useu .removeClass() Leloie, anu that coue looks coiiect. You aie using
$(this) the same way in Loth places, Lut it uoesn`t seem to woik insiue the
setTimeout() call.
88 | Chapter 5:Faster, Simpler, More Fun
Solution
Save this in a vaiiaLle Leloie calling setTimeout():
$(document).ready( function() {
$('.clicky').click( function() {
var element = this;
$(element).addClass('clicked');
setTimeout( function() {
$(element).removeClass('clicked');
}, 1000 );
});
});
Even Lettei, since you`ie calling $() in Loth places, lollow the auvice in Recipe 5.3 anu
copy $(this) to a vaiiaLle insteau ol this:
$(document).ready( function() {
$('.clicky').click( function() {
var $element = $(this);
$element.addClass('clicked');
setTimeout( function() {
$element.removeClass('clicked');
}, 1000 );
});
});
Discussion
Vhat is $(this) anyway, anu why uoesn`t it always woik? It`s easiei to unueistanu il
you sepaiate it into its two paits, $() anu this.
$() looks mysteiious, Lut it ieally isn`t: it`s just a lunction call. $ is a ieleience to the
jQuery lunction, so $() is simply a shoitei way to wiite jQuery(). It`s just an oiuinaiy
]avaSciipt lunction call that happens to ietuin an oLject.
Il you`ie using anothei ]avaSciipt liLiaiy that ieuelines $, that`s a uil-
leient matteiLut then you woulun`t use $() in youi jQueiy coue;
you`u use jQuery() oi a custom alias.
this is one ol the moie conlusing leatuies in ]avaSciipt, Lecause it`s useu loi so many
uilleient things. In oLject-oiienteu ]avaSciipt piogiamming, this is useu in an oLject`s
methous to ielei to that oLject, just like self in Python oi RuLy:
function Foo( value ) {
this.value = value;
}
Foo.prototype.alert = function() {
alert( this.value );
};
5.2 Whats Wrong with $(this)? | 89
var foo = new Foo( 'bar' );
foo.alert(); // 'bar'
In the coue loi a tiauitional onevent attiiLute, this ieleis to the element ieceiving the
eventLut only in the attiiLute itsell, not in a lunction calleu liom the attiiLute:
<a href="#" id="test" onclick="clicked(this);">Test</a>
function clicked( it ) {
alert( it.id ); // 'test'
alert( this.id ); // undefined
alert( this === window ); // true (what?)
}
As you can see liom the thiiu alert(), this is actually the window oLject insiue the
lunction. Foi histoiical ieasons, window is the uelault meaning ol this when a lunction
is calleu uiiectly (i.e., not calleu as a methou ol an oLject).
In a jQueiy event hanulei, this is the DOM element hanuling the event, so $(this) is
a jQueiy wiappei loi that DOM element. That`s why $(this).addClass() woiks as
expecteu in oui PioLlem coue.
But the coue then calls setTimeout(), anu setTimeout() woiks like a uiiect lunction
call: this is the window oLject. So when the coue calls $(this).removeClass(), it`s ac-
tually tiying to iemove the class liom the window oLject!
Vhy uoes copying this oi $(this) into a local vaiiaLle lix this? (Pun intenueu.) ]ava-
Sciipt cieates a c|osurc loi the paiameteis anu local vaiiaLles ol a lunction.
Closuies may seem mysteiious at liist, Lut they ieally Loil uown to thiee simple iules:
You can nest ]avaSciipt lunctions one insiue anothei, with multiple levels ol
nesting.
A lunction can ieau anu wiite not only its own paiameteis anu local vaiiaLles Lut
also those ol any lunctions it`s nesteu in.
The pievious iule a|ways woiks, even il the outei lunction has alieauy ietuineu
anu the innei lunction is calleu latei (e.g., an event hanulei oi setTimeout()
callLack).
These iules apply egually to all lunctions, Loth nameu anu anonymous. Howevei,
this is not a lunction paiametei oi local vaiiaLleit`s a special ]avaSciipt keywoiu
so these iules uo not apply. By copying the value ol this into a local vaiiaLle, we take
auvantage ol the closuie to make that value availaLle in any nesteu lunctions.
90 | Chapter 5:Faster, Simpler, More Fun
5.3 Removing Redundant Repetition
Problem
You neeu to hiue, show, oi otheiwise manipulate some DOM elements when the page
loaus, anu you also neeu to take the same actions latei in iesponse to a couple ol
uilleient events:
$(document).ready( function() {
// Set visibility at startup
$('#state').toggle( $('#country').val() == 'US' );
$('#province').toggle( $('#country').val() == 'CA' );
// Update visibility when country selector changes via mouse
$('#country').change( function() {
$('#state').toggle( $(this).val() == 'US' );
$('#province').toggle( $(this).val() == 'CA' );
});
// Also update when country selector changes via keyboard
$('#country').keyup( function() {
$('#state').toggle( $(this).val() == 'US' );
$('#province').toggle( $(this).val() == 'CA' );
});
});
The coue is woiking, Lut you want to simplily it so theie`s not so much uuplicate coue.
Vhy hanule Loth the change anu keyup events? Many weLsites hanule
only the change event on a select list. This woiks line il you make a
selection with the mouse, Lut il you click the select list anu then use the
up anu uown aiiow keys to select among the options, nothing happens:
keystiokes in a select list uo not liie the change event. Il you also hanule
the keyup event, the select list will iesponu to the aiiow keys, pioviuing
a Lettei expeiience loi keyLoaiu useis.
Solution 1
Move the uuplicate coue into a lunction, anu call the lunction Loth at loau time anu
in iesponse to the event. Use jQueiy`s .bind() methou to wiie up Loth event hanuleis
at the same time. Anu save uata useu moie than once in vaiiaLles:
$(document).ready( function() {
var $country = $('#country');
function setVisibility() {
var value = $country.val();
$('#state').toggle( value == 'US' );
5.3 Removing Redundant Repetition | 91
$('#province').toggle( value == 'CA' );
}
setVisibility();
$country.bind( 'change keyup', setVisibility );
});
Solution 2
Use jQueiy`s event tiiggeiing to liie the event immeuiately altei attaching it, along with
the .bind() tiick anu local vaiiaLles liom solution 1:
$(document).ready( function() {
$('#country')
.bind( 'change keyup', function() {
var value = $(this).val();
$('#state').toggle( value == 'US' );
$('#province').toggle( value == 'CA' );
})
.trigger('change');
});
Discussion
It`s stanuaiu piogiamming piactice in just aLout any language to take uuplicate coue
anu move it into a sepaiate lunction that can Le calleu liom multiple places. Solution
1 lollows this appioach: insteau ol iepeating the coue to set the visiLility, it appeais
once in the setVisibility() lunction. The coue then calls that lunction uiiectly at
staitup anu inuiiectly when the change event is liieu.
Solution 2 also uses a common lunction loi Loth ol these cases. But insteau ol giving
the lunction a name so it can Le calleu uiiectly at staitup, the coue meiely sets the
lunction as the event hanulei loi the change event anu then uses the trigger() methou
to tiiggei that same eventthus calling the lunction inuiiectly.
These appioaches aie moie oi less inteichangeaLle; it`s laigely a mattei ol taste which
you pielei.
5.4 Formatting Your jQuery Chains
Problem
You have a lengthy jQueiy chain that incluues methous like .children() anu .end() to
opeiate on seveial ielateu gioups ol elements. It`s getting haiu to tell which opeiations
apply to which elements:
$('#box').addClass('contentBox').children(':header')
.addClass('contentTitle').click(function() {
$(this).siblings('.contentBody').toggle();
92 | Chapter 5:Faster, Simpler, More Fun
}).end().children(':not(.contentTitle)')
.addClass('contentBody').end()
.append('<div class="contentFooter"></div>')
.children('.contentFooter').text('generated content');
Solution
Put each methou call in the chain on its own line, anu put the . opeiatois at the Le-
ginning ol each line. Then, inuent each pait ol the chain to inuicate wheie you aie
switching to uilleient sets ol elements.
Inciease the inuentation when you use methous like .children() oi .siblings() to
select uilleient elements, anu ueciease the inuentation when you call .end() to ietuin
to the pievious jQueiy selection.
Il you`ie new to jQueiy, you`ll pioLaLly want to ieau the iecipes aLout Lasic chaining
anu .end() in Chaptei 1:
$('#box')
.addClass('contentBox')
.children(':header')
.addClass('contentTitle')
.click(function() {
$(this).siblings('.contentBody').toggle();
})
.end()
.children(':not(.contentTitle)')
.addClass('contentBody')
.end()
.append('<div class="contentFooter"></div>')
.children('.contentFooter')
.text('generated content');
Discussion
By Lieaking each call out onto its own line, it Lecomes veiy easy to scan the coue anu
see what is happening. Using inuentation to inuicate when you`ie mouilying the set ol
elements makes it easy to keep tiack ol when uestiuctive opeiations aie occuiiing anu
Leing unuone via .end().
This style ol inuentation iesults in eveiy call loi any given set ol elements always Leing
lineu up, even il they`ie not consecutive. Foi example, it`s cleai that the wiappei
<div> has an element piepenueu anu appenueu to it, even though theie aie opeiations
on othei elements in Letween.
Putting the . opeiatois at the Leginning ol the lines insteau ol the enu is just a linishing
touch: it gives a Lettei visual ieminuei that these aie methou calls anu not oiuinaiy
lunction calls.
5.4 Formatting Your jQuery Chains | 93
Diu jQueiy invent chaining? No. jQueiy uoes make veiy goou use ol
methou chaining, Lut it`s something that has Leen aiounu since the
eailiest uays ol ]avaSciipt.
Foi example, heie is a lamiliai use ol chaining with a stiing oLject:
function htmlEscape( text ) {
return text
.replace( '&', '&' )
.replace( '<', '<' )
.replace( '>', '>' );
}
5.5 Borrowing Code from Other Libraries
Problem
You lounu a uselul lunction in anothei ]avaSciipt liLiaiy anu want to use the same
technigue in youi jQueiy coue. In this case, it`s the .radioClass() methou liom the
Ext Coie liLiaiy, which auus a class to the matching element(s) anu rcnovcs the same
class liom all siLlings ol the matching element(s).
The name .radioClass() comes liom the Lehavioi ol iauio Luttons in
Loth weL applications anu uesktop apps, wheie clicking one Lutton
selects it anu ueselects the othei Luttons in the same iauio Lutton gioup.
The name radio button loi those input elements comes liom the station
Luttons in olu cai iauiosthe mechanical ones wheie pushing in one
Lutton causeu all ol the othei Luttons to pop out.
Given this HTML:
<div>
<div id="one" class="hilite">One</div>
<div id="two">Two</div>
<div id="three">Three</div>
<div id="four">Four</div>
</div>
you`u like to iun coue like this:
// Add the 'hilite' class to div#three, and
// remove the class from all of its siblings
// (e.g. div#one)
$('#three').radioClass('hilite');
You may even want to allow a multiple-select iauio class:
// Add the 'hilite' class to div#two and
// div#four, and remove the class from the
94 | Chapter 5:Faster, Simpler, More Fun
// other siblings (div#one and div#three)
$('#two,#four').radioClass('hilite');
Solution
Viite a simple plugin to auu the .radioClass() methou to jQueiy:
// Remove the specified class from every sibling of the selected
// element(s), then add that class to the selected element(s).
// Doing it in that order allows multiple siblings to be selected.
//
// Thanks to Ext Core for the idea.
jQuery.fn.radioClass = function( cls ) {
return this.siblings().removeClass(cls).end().addClass(cls);
};
This is a shoit enough lunction that it`s not too haiu to lollow as a one-linei, Lut
inuenting the coue as uesciiLeu in Recipe 5.+ makes it completely cleai how it woiks:
jQuery.fn.radioClass = function( cls ) {
return this // Start chain, will return its result
.siblings() // Select all siblings of selected elements
.removeClass(cls) // Remove class from those siblings
.end() // Go back to original selection
.addClass(cls); // Add class to selected elements
};
Discussion
The composei Igoi Stiavinsky is iepoiteu to have saiu, Goou composeis Loiiow; gieat
composeis steal. He appaiently stole the guote liom T.S. Eliot, who wiote, Immatuie
poets imitate; matuie poets steal.
Goou iueas come liom many places, anu othei ]avaSciipt liLiaiies aie chock-lull ol
goou coue anu iueas. Il theie is coue in anothei open souice liLiaiy that you can use
oi that you can tianslate to woik with jQueiy, you`ie liee to uo thatil you iespect
the othei authoi`s copyiight anu license.
Foi inloimation on open souice anu liee soltwaie, see the lollowing
sites:
http://www.opcnsourcc.org/
http://www.jsj.org/
You may not even neeu the actual coue in a case like this one, wheie the implementation
is veiy simple anu just the idca ol having a iauio class methou is the missing link.
Vhile not ieguiieu, it`s a goou couitesy to give cieuit to the souice ol the iuea.
5.5 Borrowing Code from Other Libraries | 95
Vhethei the iuea comes liom elsewheie oi is something you thought ol youisell, in a
suipiising numLei ol cases you can wiite a uselul jQueiy plugin in one oi a lew lines
ol coue.
What Is jQuery.fn, and Why Do jQuery Plugins Use It?
jQuery.fn is a ieleience to the same oLject as jQuery.prototype. Vhen you auu a lunc-
tion to the jQuery.fn oLject, you`ie ieally auuing it to jQuery.prototype.
Vhen you cieate a jQueiy oLject with jQuery() oi $(), you`ie actually calling new
jQuery(). (The jQueiy coue automatically uoes the new loi you.) As with any othei
]avaSciipt constiuctoi, jQuery.prototype pioviues methous anu uelault piopeities loi
the oLjects ietuineu Ly each new jQuery() call. So, what you`ie ieally uoing when you
wiite a jQuery.fn plugin is tiauitional oLject-oiienteu ]avaSciipt piogiamming, auuing
a methou to an oLject using the constiuctoi`s piototype.
Then why uoes jQuery.fn exist at all? Vhy not just use jQuery.prototype like any othei
oLject-oiienteu ]avaSciipt coue? It`s not just to save a lew chaiacteis.
The veiy liist veision ol jQueiy (long Leloie 1.0) uiun`t use ]avaSciipt`s prototype
leatuie to pioviue the methous loi a jQueiy oLject. It copicd ieleiences to eveiy piopeity
anu methou in jQuery.fn (then calleu $.fn) into the jQueiy oLject Ly looping thiough
the oLject.
Since this coulu Le hunuieus ol methous anu it happeneu eveiy time you calleu $(), it
coulu Le iathei slow. So, the coue was changeu to use a ]avaSciipt piototype to elim-
inate all the copying. To avoiu Lieaking plugins that alieauy useu $.fn, it was maue an
alias ol $.prototype:
$.fn = $.prototype;
So that`s why jQuery.fn exists touayLecause plugins useu $.fn in eaily 2006!
5.6 Writing a Custom Iterator
Problem
You`ve selecteu multiple elements into a jQueiy oLject, anu you neeu to iteiate thiough
those elements with a pause Letween each iteiation, loi example, to ieveal elements
one Ly one:
<span class="reveal">Ready? </span>
<span class="reveal">On your mark! </span>
<span class="reveal">Get set! </span>
<span class="reveal">Go!</span>
You tiieu using each(), Lut ol couise that ievealeu the elements all at once:
$('.reveal').each( function() {
$(this).show();
});
96 | Chapter 5:Faster, Simpler, More Fun
// That was no better than this simpler version:
$('.reveal').show();
Solution
Viite a custom iteiatoi that uses setTimeout() to uelay the callLacks ovei time:
// Iterate over an array (typically a jQuery object, but can
// be any array) and call a callback function for each
// element, with a time delay between each of the callbacks.
// The callback receives the same arguments as an ordinary
// jQuery.each() callback.
jQuery.slowEach = function( array, interval, callback ) {
if( ! array.length ) return;
var i = 0;
next();
function next() {
if( callback.call( array[i], i, array[i] ) !== false )
if( ++i < array.length )
setTimeout( next, interval );
}
return array;
};
// Iterate over "this" (a jQuery object) and call a callback
// function for each element, with a time delay between each
// of the callbacks.
// The callback receives the same arguments as an ordinary
// jQuery(...).each() callback.
jQuery.fn.slowEach = function( interval, callback ) {
return jQuery.slowEach( this, interval, callback );
};
Then simply change youi .each() coue to use .slowEach() anu auu the timeout value:
// Show an element every half second
$('.reveal').slowEach( 500, function() {
$(this).show();
});
Discussion
jQueiy`s .each() methou is not iocket science. In lact, il we stiip the jQueiy 1.3.2
implementation uown to the coue actually useu in the most typical use (iteiating ovei
a jQueiy oLject), it`s a laiily stiaightloiwaiu loop:
jQuery.each = function( object, callback ) {
var value, i = 0, length = object.length;
for(
value = object[0];
i < length && callback.call( value, i, value ) !== false;
value = object[++i]
) {}
5.6 Writing a Custom Iterator | 97
return object;
};
That coulu also Le coueu in a moie lamiliai way:
jQuery.each = function( object, callback ) {
for(
var i = 0, length = object.length;
i < length;
++i
) {
var value = object[i];
if( callback.call( value, i, value ) === false )
break;
}
return object;
};
Ve can wiite similai lunctions to iteiate ovei aiiays oi jQueiy oLjects in othei uselul
ways. A simplei example than .slowEach() is a methou to iteiate ovei a jQueiy oLject
in ieveise:
// Iterate over an array or jQuery object in reverse order
jQuery.reverseEach = function( object, callback ) {
for( var value, i = object.length; --i >= 0; ) {
var value = object[i];
console.log( i, value );
if( callback.call( value, i, value ) === false )
break;
}
};
// Iterate over "this" (a jQuery object) in reverse order
jQuery.fn.reverseEach = function( callback ) {
jQuery.reverseEach( this, callback );
return this;
};
This uoesn`t attempt to hanule all ol the cases that .each() hanules, just the oiuinaiy
case loi typical jQueiy coue.
Inteiestingly enough, a custom iteiatoi may not use a loop at all. .reverseEach() anu
the stanuaiu .each() Loth use laiily conventional loops, Lut theie`s no explicit ]ava-
Sciipt loop in .slowEach(). Vhy is that, anu how uoes it iteiate thiough the elements
without a loop?
]avaSciipt in a weL Liowsei uoes not have a sleep() lunction as lounu in many lan-
guages. Theie`s no way to pause sciipt execution like this:
doSomething();
sleep( 1000 );
doSomethingLater();
Insteau, as with any asynchionous activity in ]avaSciipt, the setTimeout() lunction
takes a callLack that is calleu when the time inteival elapses. The .slowEach() methou
98 | Chapter 5:Faster, Simpler, More Fun
inciements the loop vaiiaLle i in the setTimeout() callLack, using a closuie to
pieseive the value ol that vaiiaLle Letween iteiations. (See Recipe 5.2 loi a uiscussion
ol closuies.)
Like .each(), .slowEach() opeiates uiiectly on the jQueiy oLject oi aiiay you give it,
so any changes you make to that aiiay Leloie it linishes iteiating will allect the iteiation.
Unlike .each(), .slowEach() is asynchionous (the calls to the callLack lunction happen
ajtcr .slowEach() ietuins), so il you change the jQueiy oLject oi its elements al-
tei .slowEach() ietuins Lut Leloie all the callLacks aie uone, that can also allect the
iteiation.
5.7 Toggling an Attribute
Problem
You neeu a way to toggle all ol the checkmaiks in a gioup ol checkLoxes. Each checkLox
shoulu Le toggleu inuepenuently ol the otheis.
Solution
Viite a .toggleCheck() plugin that woiks like the .toggle() anu .toggleClass() meth-
ous in the jQueiy coie to allow you to set, cleai, oi toggle a checkLox oi gioup ol
checkLoxes:
// Check or uncheck every checkbox element selected in this jQuery object
// Toggle the checked state of each one if check is omitted.
jQuery.fn.toggleCheck = function( check ) {
return this.toggleAttr( 'checked', true, false, check );
};
Then you can enaLle a gioup ol Luttons:
$('.toggleme').toggleCheck( true );
oi uisaLle them:
$('.toggleme').toggleCheck( false );
oi toggle them all, each one inuepenuent ol the iest:
$('.toggleme').toggleCheck();
This .toggleCheck() methou is Luilt on top ol a moie geneial-puipose .toggleAttr()
methou that woiks loi any attiiLute:
// For each element selected in this jQuery object,
// set the attribute 'name' to either 'onValue' or 'offValue'
// depending on the value of 'on. If 'on' is omitted,
// toggle the attribute of each element independently
// between 'onValue' and 'offValue'.
// If the selected value (either 'onValue' or 'offValue') is
5.7 Toggling an Attribute | 99
// null or undefined, remove the attribute.
jQuery.fn.toggleAttr = function( name, onValue, offValue, on ) {
function set( $element, on ) {
var value = on ? onValue : offValue;
return value == null ?
$element.removeAttr( name ) :
$element.attr( name, value );
}
return on !== undefined ?
set( this, on ) :
this.each( function( i, element ) {
var $element = $(element);
set( $element, $element.attr(name) !== onValue );
});
};
Vhy go to the tiouLle ol Luiluing something so geneial-puipose? Now we can wiite
similai toggleis loi othei attiiLutes with almost no elloit. Suppose you neeu to uo the
same thing as .toggleCheck(), Lut now you`ie enaLling anu uisaLling input contiols.
You can wiite a .toggleEnable() in one line ol coue:
// Enable or disable every input element selected in this jQuery object.
// Toggle the enable state of each one if enable is omitted.
jQuery.fn.toggleEnable = function( enable ) {
return this.toggleAttr( 'disabled', false, true, enable );
};
Note how the onValue anu offValue paiameteis let us swap the true anu false attiiLute
values, making it easy to talk aLout enaLling the element insteau ol the less intuitive
uisaLling that the disabled attiiLute pioviues noimally.
As anothei example, suppose we neeu to toggle a foo attiiLute wheie its on state is
the stiing value bar, anu its oll state is to iemove the attiiLute. That`s anothei
one-linei:
// Add or remove an attribute foo="bar".
// Toggle the presence of the attribute if add is omitted.
jQuery.fn.toggleFoo = function( add ) {
return this.toggleAttr( 'foo', 'bar', null, add );
};
Discussion
It`s always goou to Lewaie ol leeping cieatuiism (aka cieeping leatuiism). Il all we ieally
neeueu weie to toggle checkLoxes, we coulu coue the whole thing like this:
jQuery.fn.toggleCheck = function( on ) {
return on !== undefined ?
this.attr( 'checked', on ) :
this.each( function( i, element ) {
var $element = $(element);
$element.attr( 'checked', ! $element.attr('checked') );
100 | Chapter 5:Faster, Simpler, More Fun
});
};
That is a Lit simplei than oui .toggleAttr() methou, Lut it`s only uselul loi the
checked attiiLute anu nothing else. Vhat woulu we uo il we latei neeueu
that .toggleEnable() methou? Duplicate the whole thing anu change a lew names?
The extia woik in .toggleAttr() Luys us a lot ol llexiLility: we now can wiite a whole
lamily ol attiiLute toggleis as stiaightloiwaiu one-lineis.
Check the uocumentation loi the veision ol jQueiy you`ie using Leloie
wiiting new utility methous like this. It`s always possiLle that similai
methous coulu Le auueu to lutuie veisions ol jQueiy, saving you the
tiouLle ol wiiting youi own.
5.8 Finding the Bottlenecks
Problem
Youi site is too slow to loau oi too slow to iesponu to clicks anu othei usei inteiaction,
anu you uon`t know why. Vhat pait ol the coue is taking so much time?
Solution
Use a piolilei, eithei one ol the many availaLle ones oi a simple one you can coue
youisell.
Discussion
A piolilei is a way to linu the paits ol youi coue that take the most time. You pioLaLly
alieauy have at least one goou ]avaSciipt piolilei at youi lingeitips. FiieLug has one,
anu otheis aie Luilt into IE S anu Salaii +. These aie all lunction piolileis: you stait
pioliling, inteiact with youi page, anu stop pioliling, anu then you get a iepoit showing
how much time was spent in each lunction. That may Le enough iight theie to tell you
which coue you neeu to speeu up.
Theie aie also some piolileis specilic to jQueiy that you can linu with a weL seaich loi
jqucry proji|cr. These let you piolile selectoi peiloimance anu look moie ueeply at
jQueiy lunction peiloimance.
Foi ieally uetaileu pioliling, wheie you neeu to analyze inuiviuual sections ol coue
smallei than the lunction level, you can wiite a simple piolilei in just a lew lines ol
coue. You may have coueu this au hoc classic:
var t1 = +new Date;
// ... do stuff ...
var t2 = +new Date;
alert( ( t2 - t1 ) + ' milliseconds' );
5.8 Finding the Bottlenecks | 101
The +new Date in this coue is just a simplei way ol couing the moie
lamiliai new Date().getTime(): it ietuins the cuiient time in
milliseconus.
Vhy uoes it woik? Vell, the new Date pait is the same: it gives you a
Date oLject iepiesenting the cuiient time. (The () aie optional, as theie
aie no aiguments.) The + opeiatoi conveits that oLject to a numLei. The
way ]avaSciipt conveits an oLject to a numLei is Ly calling the oL-
ject`s .valueOf() methou. Anu the .valueOf() methou loi a Date
oLject happens to Le the same thing as .getTime(), giving the time in
milliseconus.
Ve can make something moie geneial-puipose anu easiei to use with only 15 lines
ol coue:
(function() {
var log = [], first, last;
time = function( message, since ) {
var now = +new Date;
var seconds = ( now - ( since || last ) ) / 1000;
log.push( seconds.toFixed(3) + ': ' + message + '<br />' );
return last = +new Date;
};
time.done = function( selector ) {
time( 'total', first );
$(selector).html( log.join('') );
};
first = last = +new Date;
})();
Now we have a time() lunction that we can call as olten as we want to log the elapseu
time since the last time() call (oi, optionally, since a specilic piioi time). Vhen we`ie
ieauy to iepoit the iesults, we call time.done(). Heie`s an example:
// do stuff
time( 'first' );
// do more stuff
time( 'second' );
// and more
time( 'third' );
time.done( '#log' );
That ]avaSciipt coue ieguiies this HTML coue to Le auueu to youi page:
<div id="log">
</div>
102 | Chapter 5:Faster, Simpler, More Fun
Altei the coue iuns, that <div> woulu get lilleu with a list like this:
0.102 liist
1.0++ seconu
0.0S9 thiiu
1.235 total
Ve can see that the laigest amount ol time is Leing spent Letween the time('first')
anu time('second') calls.
Bewaie ol FiieLug! Il you have FiieLug enaLleu on the page you aie
timing, it can thiow oll the iesults consiueiaLly. ]avaSciipt`s eval()
lunction, which jQueiy 1.3.2 anu eailiei use to evaluate uownloaueu
]SON uata, is allecteu to an extieme uegiee: an aiiay ol 10,000 names
anu auuiesses in the loimat liom Recipe 5.11 takes 0.2 seconus in Fiie-
lox noimally, Lut 55 scconds with FiieLug`s Sciipt panel enaLleu. Latei
veisions ol jQueiy use Function() loi this, which isn`t allecteu Ly
FiieLug.
Il FiieLug allects youi page as Lauly as that anu il you can`t linu a woik-
aiounu, you may want to uetect FiieLug anu uisplay a waining:
<div id="firebugWarning" style="display:none;">
Your warning here
</div>
$(document).ready( function() {
if( window.console && console.firebug )
$('#firebugWarning').show();
});
Foi many optimization exeicises, this coue may Le sullicient. But what il the coue we
neeu to test is insiue a loop?
for( var i = 0; i < 10; ++i ) {
// do stuff
time( 'first' );
// do more stuff
time( 'second' );
// and more
time( 'third' );
}
time.done( '#log' );
Now oui little piolilei will list those liist, seconu, anu thiiu entiies 10 times each! That`s
not too haiu to lixwe just neeu to accumulate the time spent loi each specilic message
laLel when it`s calleu multiple times:
5.8 Finding the Bottlenecks | 103
(function() {
var log = [], index = {}, first, last;
// Accumulate seconds for the specified message.
// Each message string has its own total seconds.
function add( message, seconds ) {
var i = index[message];
if( i == null ) {
i = log.length;
index[message] = i;
log[i] = { message:message, seconds:0 };
}
log[i].seconds += seconds;
}
time = function( message, since ) {
var now = +new Date;
add( message, ( now - ( since || last ) ) / 1000 );
return last = +new Date;
}
time.done = function( sel ) {
time( 'total', first );
$(sel).html(
$.map( log, function( item ) {
return(
item.seconds.toFixed(3) +
': ' +
item.message + '<br />'
);
}).join('')
);
};
first = last = +new Date;
})();
Vith this change, we`ll get uselul iesults liom that loop:
0.973 liist
9.719 seconu
0.S0+ thiiu
11.+96 total
When Timing Test Results Vary
Vhen you iun timing tests on a weL page, you won`t get the same iesult eveiy time. In
lact, the timing iesults will pioLaLly vaiy guite a Lit il you ieloau a page oi ieiun a test
multiple times.
Vhat shoulu you uo to get the ieal numLei? Aveiage the iesults?
PioLaLly not. Heie`s a chait ol the fillTable() timing liom Recipe 5.11 loi 50 con-
secutive iuns, taken aLout 10 seconus apait:
104 | Chapter 5:Faster, Simpler, More Fun
Theie`s a uistinct pattein heie: a laige majoiity ol iuns in the 150200 milliseconu
iange, with a small numLei ol scatteieu iuns taking longei. It seems likely that some-
thing aiounu 175 milliseconus is the ieal timing, anu the iuns taking much longei weie
allecteu Ly othei piocesses on the machine.
It`s also possiLle that some ol the longei iuns aie causeu Ly gaiLage collection in the
Liowsei. It woulu Le haiu to uistinguish that liom time taken Ly othei piocesses, so
the most piactical thing is pioLaLly just to uisiegaiu these outlieis.
5.9 Caching Your jQuery Objects
Problem
You`ie logging the vaiious piopeities ol the event oLject loi a mousemove event, anu the
coue lags Lehinu Lecause it uses $('.classname') selectois to linu anu upuate taLle
cells with the event uata.
Youi page contains this HTML coue loi the log:
<table id="log">
<tr><td>Client X:</td><td class="clientX"></td></tr>
<tr><td>Client Y:</td><td class="clientY"></td></tr>
<tr><td>Page X:</td><td class="pageX"></td></tr>
<tr><td>Page Y:</td><td class="pageY"></td></tr>
<tr><td>Screen X:</td><td class="screenX"></td></tr>
<tr><td>Screen Y:</td><td class="screenY"></td></tr>
</table>
anu this ]avaSciipt coue:
$('html').mousemove( function( event ) {
$('.clientX').html( event.clientX );
$('.clientY').html( event.clientY );
$('.pageX').html( event.pageX );
$('.pageY').html( event.pageY );
$('.screenX').html( event.screenX );
$('.screenY').html( event.screenY );
});
5.9 Caching Your jQuery Objects | 105
The page also contains a laige numLei (thousanus!) ol othei DOM elements. In a sim-
plei test page, the coue peiloims line, Lut in this complex page it is too slow.
Solution
Cache the jQueiy oLjects ietuineu Ly the $(...) calls, so the DOM gueiies only have
to Le iun once:
var
$clientX = $('.clientX'),
$clientY = $('.clientY'),
$pageX = $('.pageX'),
$pageY = $('.pageY'),
$screenX = $('.screenX'),
$screenY = $('.screenY');
$('html').mousemove( function( event ) {
$clientX.html( event.clientX );
$clientY.html( event.clientY );
$pageX.html( event.pageX );
$pageY.html( event.pageY );
$screenX.html( event.screenX );
$screenY.html( event.screenY );
});
You may also Le aLle to speeu up those selectois consiueiaLly; see the next iecipe loi
ways to uo that. But simply calling them once each insteau ol ovei anu ovei again may
Le enough ol an impiovement iight theie.
Discussion
One ol the classic ways to optimize coue is to hoist iepeateu calculations out ol a
loop so you have to uo them only once. Any values that uon`t change insiue the loop
shoulu Le calculateu one time, Leloie the loop staits. Il those aie expensive calculations,
the loop will then Le much lastei.
This woiks just as well when the loop is a seiies ol lieguently liieu events such as
mousemove anu the calculation is a jQueiy selectoi. Hoisting the selectoi out ol the
event hanulei makes the event hanulei iesponu lastei.
Ol couise, il you`ie calling multiple selectois insiue a loop, that will also Lenelit liom
moving them outsiue the loop in the same mannei.
106 | Chapter 5:Faster, Simpler, More Fun
Vhy uo $clientX anu the othei vaiiaLle names Legin with the $
chaiactei?
$ uoesn`t have any special meaning in ]avaSciiptit`s tieateu just like
a lettei ol the alphaLet. It`s simply a populai convention in jQueiy coue
to use the $ pielix as a ieminuei that the vaiiaLle contains a ieleience
to a jQueiy oLject anu not, say, a DOM element, Lecause a vaiiaLle
name ol $foobar has a visual iesemLlance to the jQueiy opeiation
$('#foobar').
This is especially helplul when you neeu to use Loth a jQueiy oLject anu
its unueilying DOM element, e.g.:
var $foo = $('#foo'), foo = $foo[0];
// Now you can use the jQuery object:
$foo.show();
// or the DOM element:
var id = foo.id;
5.10 Writing Faster Selectors
Problem
Youi coue contains a laige numLei ol $('.classname') selectois. You`ie caching them
as uesciiLeu in the pievious iecipe, Lut the selectois aie still allecting youi page loau
time. You neeu to make them lastei.
Solution
Fiist, make suie you aie using a iecent veision ol jQueiy (1.3.2 oi latei) loi lastei
selectoi peiloimance in most Liowseis, especially with class selectois.
Il you have contiol ovei the HTML page content, change the page to use id attiiLutes
anu '#xyz' selectois insteau ol class attiiLutes anu '.xyz' selectois:
<div class="foo"></div>
<div id="bar"></div>
$('.foo') // Slower
$('#bar') // Faster
Il you must use class name selectois, see whethei theie is a paient element that you can
linu with a lastei ID selectoi, anu then uiill uown liom theie to the chilu elements. Foi
example, using the HTML liom the pievious iecipe:
<table id="log">
<tr><td>Client X:</td><td id="clientX"></td></tr>
...
</table>
5.10 Writing Faster Selectors | 107
you coulu use this:
$('.clientX') // Slower
$('td.clientX') // May be faster
$('#log .clientX') // May be much faster
$('#log td.clientX') // Possibly faster in some browsers
Bewaie ol selectoi speeu test pages that uon`t iellect the actual page
content you aie using. In a veiy simple page, a simple $('.clientX')
selectoi may test out lastei than a lanciei selectoi like
$('#log td.clientX')even in Liowseis anu jQueiy veisions wheie
you might expect the class selectoi to Le slow.
That`s just Lecause the moie complicateu selectoi takes moie time to
set up, anu in a simple page that setup time may uominate peiloimance.
The test page loi this iecipe ueliLeiately contains a veiy laige numLei
ol elements to piovoke selectoi peiloimance pioLlems that only show
up in laige pages.
Neithei one, ol couise, shows exactly what any selectoi`s peiloimance
will Le in your page. The only way to Le suie which selectoi is lastest in
a paiticulai page is to test each in that page.
Discussion
It`s easy to loiget that an innocent-looking call like $('.clientX') may take consiuei-
aLle time. Depenuing on the Liowsei anu veision ol jQueiy, that selectoi may have to
make a list ol eveiy DOM element in youi page anu loop thiough it looking loi the
specilieu class.
jQueiy veisions piioi to 1.3 use this slow methou in cvcry Liowsei. jQueiy 1.3 intio-
uuceu the Sizzle selectoi engine, which takes auvantage ol lastei DOM APIs in newei
Liowseis such as getElementsByClassName() anu querySelectorAll().
Howevei, loi most weLsites you`ll pioLaLly neeu to suppoit IE 7 loi some time to come,
anu class selectois aie slow in IE 7 when you have a complex page.
Il you can use it, selecting Ly ID as in $('#myid') is geneially veiy last in all Liowseis,
Lecause it simply uses a single call to the getElementById() API.
It also helps to naiiow uown the numLei ol elements that neeu to Le seaicheu, eithei
Ly specilying a paient element, Ly making the class selectoi moie specilic with a tag
name, oi Ly comLining those anu othei tiicks.
108 | Chapter 5:Faster, Simpler, More Fun
5.11 Loading Tables Faster
Problem
You`ie loauing a ]SON uata oLject with 1,000 names anu auuiesses anu using jQueiy
to cieate a taLle with this uata. It takes 510 seconus to cieate the taLle in IE 7anu
that`s not even counting the uownloau time.
Youi ]SON uata is in this loimat:
{
"names": [
{
"first": "Azzie",
"last": "Zalenski",
"street": "9554 Niemann Crest",
"city": "Quinteros Divide",
"state": "VA",
"zip": "48786"
},
// and repeat for 1000 names
]
}
Youi ]avaSciipt coue is as lollows:
// Return a sanitized version of text with & < > escaped for HTML
function esc( text ) {
return text
.replace( '&', '&' )
.replace( '<', '<' )
.replace( '>', '>' );
}
$(document).ready( function() {
function fillTable( names ) {
$.each( names, function() {
$('<tr>')
.append( $('<td>').addClass('name').html(
esc(this.first) + ' ' + esc(this.last)
) )
.append( $('<td>').addClass('address').html(
esc(this.street) + '<br />' +
esc(this.city) + ', ' +
esc(this.state) + ' ' + esc(this.zip)
) )
.appendTo('#nameTable');
});
}
$.getJSON( 'names/names-1000.json', function( json ) {
fillTable( json.names );
});
});
5.11 Loading Tables Faster | 109
Anu you have this HTML coue in youi uocument:
<table id="nameTable">
</table>
It woiks line, iesulting in the Liowsei uisplay shown in Figuie 5-1.
Iigurc 5-1. Browscr output jor nanc tab|c
It`s just much too slow.
Solution
ComLine seveial optimizations:
Inseit a single <table> oi <tbody> insteau ol multiple <tr> elements
Use .innerHTML oi .html() insteau ol DOM manipulation
Builu an aiiay with a[++i] anu .join() it insteau ol stiing concatenation
Use a Laie-metal for loop insteau ol $.each
Reuuce name lookups
The iesult is this new veision ol the coue (using the same esc() lunction as Leloie):
$(document).ready( function() {
function fillTable( names ) {
// Reduce name lookups with local function name
var e = esc;
//
var html = [], h = 1;
html[++h] = '<table id="nameTable">';
html[++h] = '<tbody>';
for( var name, i = 1; name = names[++i]; ) {
html[++h] = '<tr><td class="name">';
html[++h] = e(name.first);
110 | Chapter 5:Faster, Simpler, More Fun
html[++h] = ' ';
html[++h] = e(name.last);
html[++h] = '</td><td class="address">';
html[++h] = e(name.street);
html[++h] = '<br />';
html[++h] = e(name.city);
html[++h] = ', ';
html[++h] = e(name.state);
html[++h] = ' ';
html[++h] = e(name.zip);
html[++h] = '</td></tr>';
}
html[++h] = '</tbody>';
html[++h] = '</table>';
$('#container')[0].innerHTML = html.join('');
}
$.getJSON( 'names/names-1000.json', function( json ) {
fillTable( json.names );
});
});
The new coue ieguiies the HTML coue in youi uocument to Le changeu to the
lollowing:
<div id="container">
</div>
On one test system in IE 7, the new coue iuns in 0.2 seconus compaieu with 7 seconus
loi the oiiginal coue. That`s 35 times lastei!
Gianteu, the coue is not as clean anu elegant as the oiiginal, Lut youi site`s visitois will
nevei know oi caie aLout that. Vhat they will notice is how much lastei youi page
loaus.
Discussion
Sometimes you`ll get lucky anu linu that one specilic optimization is all it takes to lix
a peiloimance pioLlem. Sometimes, as in this iecipe, you`ll neeu seveial tiicks to get
the speeu you want.
The Liggest speeu Loost in this coue comes liom inseiting a single <table> element with
all its chiluien in a single DOM opeiation, insteau ol inseiting a lengthy seiies ol
<tr> elements one Ly one. In oiuei to uo this, you neeu to geneiate the entiie taLle as
HTML. That means you neeu to paste togethei a laige numLei ol stiings to Luilu the
HTML, which can Le veiy last oi veiy slow uepenuing on how you uo it. Anu with
1,000 items to loop though, it`s woith linuing the lastest way to wiite the loop itsell.
You may wonuei, Is this still jQueiy coue? It looks like plain olu ]avaSciipt! The
answei is yes, anu yes. It`s guite all iight to mix anu match jQueiy coue with othei
]avaSciipt coue. You can use simplei jQueiy ways ol couing in most ol youi site, anu
5.11 Loading Tables Faster | 111
when you uiscovei the slow paits, you can eithei linu lastei jQueiy technigues oi use
plain olu ]avaSciipt as neeueu loi peiloimance.
5.12 Coding Bare-Metal Loops
Problem
You`ie calling $.each(array,fn) oi $(selector).each(fn) to iteiate ovei thousanus ol
items in youi coue, anu you suspect that all those lunction calls may Le auuing to youi
loau time:
$.each( array, function() {
// do stuff with this
});
oi:
$('.lotsOfElements').each( function() {
// do stuff with this or $(this)
});
Solution
Use a for loop insteau ol .each(). To iteiate ovei an aiiay, it`s haiu to Leat this loop:
for( var item, i = 1; item = array[++i] ) {
// do stuff with item
}
But theie is a catch: this loop woiks only il youi aiiay has no lalse elements, that is,
elements whose value is undefined, null, false, 0, oi "". Even with that iestiiction, this
loop is uselul in many common cases, such as iteiating ovei a jQueiy oLject. ]ust Le
suie to cache the oLject in a vaiiaLle:
var $items = $('.lotsOfElements');
for( var item, i = 1; item = $item[++i] ) {
// do stuff with item (a DOM node)
}
It`s also common to have ]SON uata that contains an aiiay ol oLjects as in oui example
liom Recipe 5.11:
{
"names": [
{
// ...
"zip": "48786"
},
// and repeat for 1000 names
]
}
112 | Chapter 5:Faster, Simpler, More Fun
Il you know that none ol the oLjects making up the elements ol the names aiiay will
evei Le null, it`s sale to use the last loop.
Foi a moie geneial-puipose loop that woiks with any aiiay, theie is always the classic
loop that you`ll see in many places:
for( var i = 0; i < array.length; i++ ) {
var item = array[i];
// do stuff with item
}
But you can impiove that loop in thiee ways:
Cache the aiiay length.
Use ++i, which is lastei than i++ in some Liowseis.
ComLine the test anu inciement ol the loop vaiiaLle to iemove one name lookup.
The iesult is as lollows:
for( var i = 1, n = array.length; ++i < n; ) {
var item = array[i];
// do stuff with item
}
Voulu it Le even lastei to use a while loop oi a do...while loop? PioL-
aLly not. You coulu iewiite the pievious loop as lollows:
var i = 1, n = array.length;
while( ++i < n ) {
var item = array[i];
// do stuff with item
}
oi:
var i = 0, n = array.length;
if( i < n ) do {
var item = array[i];
// do stuff with item
}
while( ++i < n );
But neithei one is any lastei than the moie ieauaLle for loop.
To iteiate ovei an oLject (not an aiiay), you can use a for..in loop:
for( var key in object ) {
var item = object[key];
// do stuff with item
}
5.12 Coding Bare-Metal Loops | 113
A Warning About for..in Loops
Nevei use a for..in loop to iteiate ovei a jQueiy oLject oi an aiiay ol any type. Il the
aiiay has any custom piopeities oi methous, those will Le iteiateu along with the nu-
meiic aiiay elements. Foi example, this coue enumeiates a single DOM element, the
uocument Louy (with i = 0):
$('body').each( function( i ) { console.log( i ); });
This coue may look like it woulu uo the same thing, Lut it enumeiates all ol the jQueiy
methous such as show anu css along with the [0] element:
for( var i in $('body') ) console.log( i ); // BAD
Insteau, use one ol the aiiay loops listeu pieviously.
Even the sale use ol a for..in loop to iteiate ovei an oLject can get in tiouLle il any
coue on youi page has mouilieu Object.prototype to extenu all oLjects with auuitional
methous oi piopeities. The loop will enumeiate those methous oi piopeities along
with the ones you want.
Extenuing Object.prototype is stiongly uiscouiageu Lecause it Lieaks so much coue.
In lact, at least thiough jQueiy 1.3.2, it Lieaks jQueiy itsell Ly causing each() to enu-
meiate those auueu methous oi piopeities. Il youi coue has to woik in such an envi-
ionment, you neeu to take extia piecautions on all youi loops, such as testing the
hasOwnProperty() methou ol each oLject piopeity. Unloitunately, these extia tests slow
the coue uown, so you have to choose Letween speeu anu ioLustness.
Discussion
$(selector).each(fn) is the customaiy way to cieate a jQueiy oLject anu iteiate ovei
it, Lut it`s not the only way. The jQueiy oLject is an aiiay-like oLject with .length
anu [0], [1], ..., [length-1] piopeities. Theieloie, you can use any ol the looping
technigues you woulu use with any othei aiiay. Anu Lecause the jQueiy oLject nevei
contains lalse elements, you can use the lastest for loop listeu at the Leginning ol the
solution.
Il you use the time() lunction liom Recipe 5.2 oi anothei piolilei to measuie loop
peiloimance, Le suie to test youi actual coue, not a simplilieu test case that just iuns
the loop without the lull loop Louy. The simplilieu test woulu miss one potential Lenelit
ol the for loop: lewei name lookups iesulting liom less lunction nesting. See Rec-
ipe 5.13 loi the uetails.
114 | Chapter 5:Faster, Simpler, More Fun
5.13 Reducing Name Lookups
Problem
Youi coue has an innei loop, uown insiue seveial levels ol nesteu lunctions, that iuns
hunuieus oi thousanus ol times. The innei loop calls seveial gloLal lunctions, anu it
ieleiences some vaiiaLles uelineu in the outei lunctions oi gloLally.
Each ol these ieleiences is tiiggeiing seveial name lookups Lecause ol the nesteu lunc-
tions. It`s slowing uown youi coue, Lut piolileis uon`t show what the pioLlem is, anu
it isn`t oLvious liom looking at the coue that theie`s a pioLlem!
Solution
Investigate eveiy name that appeais in youi inneimost loop, anu liguie out how many
name lookups it ieguiies. Reuuce the numLei ol name lookups Ly caching oLject iel-
eiences locally oi using lewei nesteu lunctions.
Discussion
Closuies aie a wonueilul thing. They make it tiivial to captuie state inloimation anu
pass it along to asynchionous lunctions such as event hanuleis oi timei callLacks. Il
]avaSciipt uiun`t have closuies, then eveiy asynchionous callLack woulu neeu to have
a way to pass that state aiounu. Insteau, you can simply use a nesteu lunction.
The uynamic natuie ol ]avaSciipt is also a wonueilul thing. You can auu piopeities
anu methous to any oLject, any time, anu the ]avaSciipt iuntime will happily chase
uown those ieleiences when you neeu them.
Put these togethei, anu you can get a lot ol name lookups.
The most mouein ]avaSciipt inteipieteis have impioveu gieatly in this
aiea. But il you want youi coue to iun last in the most populai
Liowseissuch as any veision ol IE you still neeu to woiiy aLout the
numLei ol name lookups.
Consiuei this coue:
// A typical function wrapper to get a local scope
(function() {
// Find the largest absolute value in an array of numbers
function maxMagnitude( array ) {
var largest = -Infinity;
$.each( array, function() {
largest = Math.max( largest, Math.abs(this) );
});
return largest;
}
5.13 Reducing Name Lookups | 115
// Other code here calls maxMagnitude on a large array
})();
RememLei that ]avaSciipt looks up a name liist in the local scope (lunction), anu il the
name isn`t lounu theie, it woiks its way up thiough the paient nesteu lunctions anu
linally the gloLal scope. Not only uoes the ]avaSciipt iuntime have to look up each
name eveiy time you use it, it also has to iepeat those lookups when the names aie
actually uelineu in paient lunctions oi in the gloLal scope.
So, il this Llock ol coue is in the gloLal scope, the each() callLack uoes the lollowing
name lookups in eveiy iteiation:
1. largest in local scope lail
2. largest in MaxMagnitude() success
3. Math in local scope lail
+. Math in MaxMagnitude() lail
5. Math in anonymous wiappei lunction lail
6. Math in gloLal scope success
7. abs in Math oLject success
S. Math in local scope lail
9. Math in MaxMagnitude() lail
10. Math in anonymous wiappei lunction lail
11. Math in gloLal scope success
12. max in Math oLject success
13. largest in local scope lail
1+. largest in MaxMagnitude() success
Now iewiite the coue as lollows:
// A typical wrapper to get a local scope
(function() {
// Find the largest absolute value in an array of numbers
function maxMagnitude( array ) {
var abs = Math.abs, max = Math.max;
var largest = -Infinity;
for( var i = 1, n = array.length; ++i < n; ) {
largest = max( largest, abs(array[i]) );
}
return largest;
}
// Other code here calls maxMagnitude on a large array
})();
This not only eliminates the callLack lunction call in eveiy iteiation, it also ieuuces the
numLei ol name lookups pei iteiation Ly 10 oi moie. The loop Louy in this veision
uoes these name lookups:
1. laigest in local scope success
2. aLs in local scope success
3. max in local scope success
+. laigest in local scope success
That`s moie than a 70 peicent impiovement ovei the liist veision.
116 | Chapter 5:Faster, Simpler, More Fun
Il this coue is nesteu even ueepei insiue anothei lunction, the uilleience is even gieatei,
since each nesteu lunction auus one moie lookup loi each ol the Math oLject lookups.
In this uiscussion we`ie omitting the this anu array[i] lookups, as well
as the lookups in the for loop itsell. Those aie ioughly compaiaLle Le-
tween the two veisions.
In Recipe 5.11, a single name lookup optimization accounts loi a 100 ms impiovement.
That`s not a huge uilleience, Lut a tenth ol a seconu oll youi page loau time loi a one-
line coue change is goou value.
The oiiginal coue calls esc() six times in each loop iteiation, loi a total ol 6,000 calls
in the thousanu-name test case. These calls aie insiue thiee nesteu lunctions, anu
esc() is a gloLal lunction, so it takes loui name lookups simply to iesolve the lunction
name loi each call. That`s 2+,000 name lookups!
The impioveu coue ieuuces the lunction nesting Ly one, so that cuts it uown to 1S,000
name lookups (two nesteu lunctions anu the gloLal scope at 6,000 each), Lut then it
uses one last tiick in the inneimost lunction:
function fillTable( names ) {
var e = esc;
// and now call e() in the inner loop instead of esc()
}
Now, the 6,000 calls to e() aie each iesolveu in a single name lookup. That`s a
ieuuction ol 12,000 name lookups. No wonuei it knocks a tenth ol a seconu oll the
loau time.
5.14 Updating the DOM Faster with .innerHTML
Problem
You`ie cieating a laige Llock ol HTML coue anu using $('#mydiv').html(myhtml); to
inseit it into the DOM. You`ve piolileu the coue anu lounu that the .html() methou is
taking longei than expecteu.
Solution
Use $('#mydiv')[0].innerHTML = myhtml; loi lastei DOM upuatesil you uon`t
ieguiie any ol the special piocessing that .html() pioviues.
Discussion
The .html() methou uses the .innerHTML piopeity to actually inseit the HTML content
into the DOM, Lut it uoes guite a Lit ol piepiocessing liist. In most cases this won`t
5.14 Updating the DOM Faster with .innerHTML | 117
mattei, Lut in peiloimance-ciitical coue you can save some time Ly setting
the .innerHTML piopeity uiiectly.
It`s actually jQueiy`s inteinal .clean() methou that uoes this piocessing. Il you ieau
the souice coue loi .clean(), you`ll see that it goes to guite a Lit ol woik to clean up
the HTML input.
The easiest way to linu most methous in the jQueiy souice coue is to
seaich loi the methou name with a : altei it; e.g., to linu the .clean()
methou, seaich loi clean: in the unconprcsscd jQueiy souice.
The coue in Recipe 5.11 iuns aloul ol some ol this cleanup. That iecipe`s HTML coue
contains a laige numLei ol <br /> tags. Theie`s a iegulai expiession in .clean() that
linus all sell-closing tags (tags that enu with /> anu theieloie uo not ieguiie a closing
tag) anu checks that these tags aie inueeu in the limiteu set ol HTML tags that can Le
sell-closeu. Il not, then it conveits the HTML to an openclose tag.
Foi example, il you coue $('#test').html('<div />');, then this invaliu HTML is au-
tomatically conveiteu to $('#test').html('<div></div>');. This makes couing easiei,
Lut il you have a veiy long HTML stiing that contains many sell-closing
tags, .clean() has to check them alleven il all those tags aie valiu like the <br /> tags
in the othei iecipe.
The .html() methou ieplaces any existing content, anu it takes caie to avoiu memoiy
leaks Ly iemoving all event hanuleis that you`ve attacheu thiough jQueiy to any ol the
elements Leing ieplaceu. Il theie aie any event hanuleis in the content Leing ieplaceu,
you shoulu stick with .html(), oi il you just neeu this event hanulei cleanup Lut uon`t
neeu the othei HTML cleanup, you coulu possiLly use $('#test').empty()
[0].innerHTML = myhtml; to get the event cleanup only.
The Lottom line: il you know loi suie that youi coue uoesn`t ieguiie the event cleanup
oi HTML cleanup that jQueiy noimally pioviues, then with caution you can
use .innerHTML uiiectly. Otheiwise, stick with .html() loi salety.
5.15 Debugging? Break Those Chains
Problem
A chain ol jQueiy methous is lailing somewheie along the way. The HTML coue is as
lollows:
<div class="foo">
before
<span class="baz" style="display:none;">
test
</span>
118 | Chapter 5:Faster, Simpler, More Fun
after
</div>
anu the ]avaSciipt coue (pait ol a Lutton click event hanulei) is as lollows:
$('.foo').css({ fontsize: '18px' }).find('.bar').show();
But when you iun the coue, the lont size isn`t set, anu the hiuuen element isn`t shown.
You have FiieLug oi anothei ]avaSciipt ueLuggei, Lut it`s haiu to tiace thiough the
coue. How can you tell wheie in the chain it is lailing?
Solution
Bieak up the chain into inuiviuual statements, anu stoie each jQueiy oLject in a
vaiiaLle:
// $('.foo').css({ fontsize: '18px' }).find('.bar').show();
var $foo = $('.foo');
$foo.css({ fontsize: '18px' });
var $bar = $foo.find('.bar');
$bar.show();
Now you have seveial ueLugging options. One is to use the Step Ovei commanu in the
ueLuggei to single step ovei each statement anu oLseive youi vaiiaLles anu the state
ol the page altei each step.
In this coue, you`u want to check $foo anu $bar altei theii values aie assigneu. Vhat
is the value ol the .length piopeity ol each? That tells you how many DOM elements
weie selecteu. Does each oLject contain the DOM elements you expect? Check the [0],
[1], [2], etc., piopeities to see the DOM elements.
Assuming that $foo contains the coiiect DOM elements, what happens altei
the .css() methou is calleu? Vith FiieLug`s CSS Inspectoi, you`ll linu that the CSS
font-size piopeity is unchangeu altei the methou call. Vait a minute! It`s font-size,
not fontsize? Theie`s the pioLlem. Checking the uocs, you linu that the coiiect way
to wiite this is eithei ol these:
$foo.css({ fontSize: '18px' });
$foo.css({ 'font-size': '18px' });
That`s one pioLlem uown, Lut what aLout the othei one? Altei $bar is assigneu, il we
look at its .length piopeity, we`ll see that it is zeio. This tells us that we uiun`t succeeu
in selecting any elements. A look at the HTML anu ]avaSciipt coue will then ieveal that
we simply misspelleu the class name.
Now we can incoipoiate these two lixes Lack in the oiiginal chain:
$('.foo').css({ fontSize: '18px' }).find('.baz').show();
Anothei alteinative is to use FiieLug`s logging statements:
// $('.foo').css({ fontsize: '18px' }).find('.bar').show();
var $foo = $('.foo');
5.15 Debugging? Break Those Chains | 119
console.log( $foo );
$foo.css({ fontsize: '18px' });
console.log( $foo.css('fontsize') );
var $bar = $foo.find('.bar');
console.log( $bar );
$bar.show();
These console.log() calls will ieveal that $bar uoesn`t have any elements selecteu,
although we`ve lallen into a tiap on the call that attempts to log the lont size: we
misspelleu fontSize in the console.log() call as well!
This is wheie comLining multiple ueLugging technigues helps: log those vaiiaLles, use
FiieLug`s inspectois, ieau anu ieieau youi souice coue, anu have someone else look at
the pioLlem too.
Discussion
jQueiy`s chaining helps make it easy to wiite concise coue, Lut it can get in the way
when ueLugging, Lecause it is haiu to step thiough the inuiviuual steps ol the chain
anu see theii iesults. Bieaking up the chain into inuiviuual statements, even on a tem-
poiaiy Lasis while ueLugging, makes this task easiei.
5.16 Is It a jQuery Bug?
Problem
You`ie calling some jQueiy coue to show a hiuuen element anu set its HTML content
altei a time uelay using setTimeout():
function delayLog( text ) {
setTimeout( "$('#log').show().html(text)", 1000 );
}
// ... and somewhere else in the code ...
delayLog( 'Hello' );
The .show() call woiks, Lut the .html(text) call lails. The FiieLug console iepoits that
the text vaiiaLle is unuelineu. The same jQueiy coue woiks when you uon`t call it liom
setTimeout(). Is theie a pioLlem using jQueiy with setTimeout()?
Solution
One way to linu out whethei jQueiy is the souice ol a pioLlem is to ieplace youi jQueiy
coue with othei ]avaSciipt coue that uoesn`t use jQueiy. In this example, we can ieplace
the jQueiy coue with a simple alert():
function delayLog( text ) {
setTimeout( "alert(text)", 1000 );
}
120 | Chapter 5:Faster, Simpler, More Fun
Vhen we tiy this veision ol the coue, the same pioLlem occuis: theie is no aleit, anu
FiieLug again iepoits that text is unuelineu.
This uoesn`t iuentily the pioLlem, Lut it naiiows it uown a lot. It cleaily isn`t jQueiy
(unless the meie piesence ol the jQueiy liLiaiy is inteileiing with youi page, Lut you
can iule that out Ly iunning the coue in a simple test page that uoesn`t incluue jQueiy).
So, it must Le something wiong with this coue itsell, most likely to uo with the way
we`ie using setTimeout().
Inueeu, the pioLlem heie is that when a stiing aigument is passeu to setTimeout(), it
is executeu in the g|oba| scopc, i.e., as il the coue weie locateu outsiue ol any lunction.
The easiest way to lix it is to use a local lunction loi the callLack insteau ol a text stiing:
function delayLog( text ) {
setTimeout( function() {
alert(text);
}, 1000 );
}
Unlike coue in a stiing, a nesteu lunction has lull access to the outei lunction`s vaiiaLles
anu paiameteis. So, this coue will aleit the text as expecteu.
Anu linally, heie is a coiiecteu veision ol the oiiginal jQueiy coue:
function delayLog( text ) {
setTimeout( function() {
$('#log').show().html(text);
}, 1000 );
}
Discussion
Vhen ueLugging, il you aien`t suie what is causing a pioLlem, linuing out wheie the
pioLlem isn`t can help you tiack it uown. The puipose ol this iecipe isn`t to help you
tiouLleshoot setTimeout() pioLlemsaltei all, this is a jQueiy Look, not a geneial
]avaSciipt LookLut to help you locus youi ueLugging elloits Ly guickly iuling out
(oi conliiming!) jQueiy as the souice ol the pioLlem.
5.17 Tracing into jQuery
Problem 1
You`ie using the Step Into leatuie in FiieLug oi anothei ]avaSciipt ueLuggei to tiy to
step thiough the jQueiy coue to see what it actually uoes when you make a jQueiy call.
But when you step into the jQueiy coue, it`s all masheu into one long, unieauaLle line
ol coue anu you can`t step thiough it:
(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F)...
5.17 Tracing into jQuery | 121
Solution 1
You`ie using the ninijicd veision ol jQueiy. Insteau, loau the unconprcsscd veision ol
jQueiy into youi page loi testing.
Il you aie loauing the coue liom the Google Ajax LiLiaiies API with a <script> tag,
change it like this:
<!-- Comment out the minified jQuery -->
<!--
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js
"></script>
-->
<!-- Use the uncompressed version for testing -->
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
Il you`ie using Google`s ]avaSciipt loauei, change it like this:
// Comment out the minified jQuery
// google.load( 'jquery', '1.3.2' );
// Use the uncompressed version for testing
google.load( 'jquery', '1.3.2', { uncompressed:true });
Now you will Le aLle to step into anu thiough the jQueiy coue.
Problem 2
Having lixeu that pioLlem, you want to leain how jQueiy`s .html() anu .show() meth-
ous woik. So, you aie tiying to tiace into this coue in the ueLuggei:
$('#test').html( 'test' ).show();
But when you use the Step Into commanu, the ueLuggei goes into the jQueiy con-
stiuctoi insteau ol eithei ol the methous that you`ie inteiesteu in.
Solution 2
The pievious line ol coue contains thrcc lunction calls: a call to the jQueiy ($) con-
stiuctoi lolloweu Ly calls to the .html() anu .show() methous. The Step Into commanu
steps into the liist ol those calls, the constiuctoi.
At that point you can immeuiately uo a Step Out lolloweu Ly anothei Step In. This
steps you out ol the jQueiy constiuctoi (thus putting you Lack in the nidd|c ol the
oiiginal line ol coue) anu then into the .html() methou.
To get to the .show() methou, use anothei paii ol Step Out anu Step In commanus.
Each time you uo this, you`ll woik youi way one step luithei thiough the jQueiy chain.
Il this gets teuious, Lieak the chain as uesciiLeu in Recipe 5.15, anu auu debugger;
statements wheievei you want to stop. Il you want to tiace into the .show() methou,
you can change the coue to the lollowing:
122 | Chapter 5:Faster, Simpler, More Fun
var $test = $('#test');
$test.html( 'test' );
debugger;
$test.show();
Now when the coue stops on the debugger; statement, you can just use Step In (twice,
liist to step to the $test.show(); statement anu then to step into that lunction call).
You coulu use Step Ovei to step liom the debugger; statement to the
next line, since altei all you`ie not yet stepping into anything, Lut it`s
easiei to click Step In (oi hit the F11 key in Vinuows) twice, anu it woiks
just as well. Oi, insteau ol the debugger; statement, you can set a Lieak-
point on the $test.show() line itsell, anu then a single Step In will go
into the coue loi the .show() methou.
Discussion
The minilieu veision ol jQueiy is gieat loi piouuction use Lut not so goou loi uevel-
opment. It collapses all ol the coue into one oi two lines, making it neaily impossiLle
to step thiough the coue in a ueLuggei. Also, the common use ol chaineu methous
makes it moie uillicult to step into jQueiy methous. Using the tips in this iecipe, you
can easily tiace thiough the jQueiy coue in the ueLuggei, whethei to chase uown a Lug
oi to leain how the coue woiks.
Do not let youi test-uiiven liienus talk you out ol using a ueLuggei! Even
il you linu most ol youi Lugs thiough unit testing anu othei means, one
ol the Lest ways to leain aLout a piece ol coue is to step thiough it in
the ueLuggei anu stuuy its vaiiaLles anu piopeities as you go.
Altei all, as you ieau coue, you have to step thiough it in youi heau anu
loim a mental mouel ol what its vaiiaLles contain. Vhy not let the
computei step thiough the coue anu show you what`s in those vaiiaLles?
5.18 Making Fewer Server Requests
Problem
You`ie incluuing jQueiy anu a numLei ol plugins in youi page. The sheei numLei ol
seivei ieguests is slowing uown youi page loau time:
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="superfish.js"></script>
<script type="text/javascript" src="cycle.js"></script>
<script type="text/javascript" src="history.js"></script>
<script type="text/javascript" src="hoverintent.js"></script>
<script type="text/javascript" src="jcarousel.js"></script>
5.18 Making Fewer Server Requests | 123
<script type="text/javascript" src="thickbox.js"></script>
<script type="text/javascript" src="validate.js"></script>
Altei the page loaus, you aie uownloauing some ]SON uata using $.getJSON(), thus
auuing yet anothei seivei ieguest:
$(document).ready( function() {
$.getJSON( 'myjson.php?q=test', function( json ) {
$('#demo').html( json.foo );
});
});
myjson.php is a sciipt on youi seivei that ietuins ]SON uata like this:
{
"foo": "bar"
}
Solution
Loau jQueiy liom Google`s Ajax liLiaiy, anu comLine all youi plugins into a single lile:
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="plugins.js">
</script>
Oi, comLine a|| ol the ]avaSciipt coue you use most lieguently (jQueiy, plugins, anu
youi own coue) into a single lile:
<script type="text/javascript" src="allmyscripts.js"></script>
Eithei way, it also helps to ninijy the .js liles (iemove comments anu extia whitespace)
to ieuuce theii size. Anu make suie youi seivei is using gzip compiession on the liles
it uownloaus.
Foi the ]SON uata, since this page is geneiateu Ly youi own seivei application, you
can Luin the ]SON uata uiiectly into the HTML page as it`s geneiateu, using a
<script> tag:
<script type="text/javascript">
var myJson = {
"foo": "bar"
};
</script>
The highlighteu poition ol that sciipt tag is iuentical to the ]SON uata uownloaueu Ly
myjson.php in the oiiginal coue. In most seivei languages it shoulu Le easy to incluue
the content in this way.
Now the jQueiy coue to use the ]SON uata is simply:
$(document).ready( function() {
$('#demo').html( myJson.foo );
});
124 | Chapter 5:Faster, Simpler, More Fun
This eliminates one moie seivei ieguest.
Discussion
One ol the keys to last page loauing is to simply minimize the numLei ol HTTP ieguests.
Making ieguests to uilleient seiveis can also help. Biowseis will make only a small
numLei ol simultaneous uownloaus liom any single uomain (oi suLuomain), Lut il you
uownloau some ol youi liles liom a uilleient uomain, the Liowsei may uownloau them
in paiallel as well.
Pointing uilleient <script> tags to uilleient uomains may allow them to
Le uownloaueu in paiallel, Lut it uoesn`t allect the oiuei ol cxccution.
<script> tags aie executeu in the oiuei they appeai in the HTML souice.
You can comLine ]avaSciipt liles Ly hanu Ly simply copying anu pasting them into one
Lig lile. This is inconvenient loi uevelopment Lut uoes speeu up uownloauing.
Theie aie a numLei ol lile comLinei/minilieis availaLle loi vaiious seivei languages.
RuLy on Rails:
Bunule-lu
AssetPackagei
The packagei Luilt into Rails 2.0
PHP:
Minily
Python:
]SCompile
]ava:
YUI Compiessoi
In auuition to ]avaSciipt coue, check youi CSS loi multiple .css liles. Some ol the tools
listeu can meige youi .css liles into a single uownloau, just as they uo loi .js liles.
At one time, packing ]avaSciipt was all the iage. This not only ie-
moves comments anu whitespace Lut also iewiites all ol the ]avaSciipt
coue so that it`s not even ]avaSciipt coue anymoie. Packing ieguiies an
unpacking step at iuntimeeveiy time the page loaus, even il the ]ava-
Sciipt coue is alieauy cacheu. Because ol this, packing has lallen out ol
lavoi, anu minilying the coue (iemoving comments anu whitespace)
is iecommenueu insteau, comLineu with gzip compiession. Much ol
the Lenelit ol packing comes liom iemoving uuplicate stiings, anu gzip
uoes that loi you anyway.
5.18 Making Fewer Server Requests | 125
5.19 Writing Unobtrusive JavaScript
Problem
You have a page with inline event hanulei attiiLutes cieating a hovei ellect loi a menu.
Youi content (HTML), piesentation (CSS), anu Lehavioi (]avaSciipt) aie all mixeu up,
making it haiu to maintain each on theii own anu iesulting in uuplicate ]avaSciipt anu
style settings:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="en-us" />
<title>Menu Demo</title>
<style type="text/css">
.menu {
background-color: #ccc;
list-style: none;
margin: 0;
padding: 0;
width: 10em;
}
.menu li {
margin: 0;
padding: 5px;
}
.menu a {
color: #333;
}
</style>
</head>
<body>
<ul class="menu">
<li onmouseover="this.style.backgroundColor='#999';"
onmouseout="this.style.backgroundColor='transparent';">
<a href="download.html">Download</a>
</li>
<li onmouseover="this.style.backgroundColor='#999';"
onmouseout="this.style.backgroundColor='transparent';">
<a href="documentation.html">Documentation</a>
</li>
<li onmouseover="this.style.backgroundColor='#999';"
onmouseout="this.style.backgroundColor='transparent';">
<a href="tutorials.html">Tutorials</a>
</li>
</ul>
</body>
</html>
126 | Chapter 5:Faster, Simpler, More Fun
Solution
Replace inline ]avaSciipt with jQueiy event hanuleis, anu auu/iemove classes insteau
ol manipulating the backgroundColor style uiiectly:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="en-us" />
<title>Menu Demo</title>
<style type="text/css">
.menu {
background-color: #ccc;
list-style: none;
margin: 0;
padding: 0;
width: 10em;
}
.menu li {
margin: 0;
padding: 5px;
}
.menu a {
color: #333;
}
.menuHover {
background-color: #999;
}
</style>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js">
</script>
<script type="text/javascript">
$(document).ready( function() {
$('li').hover(
function() {
$(this).addClass('menuHover');
},
function() {
$(this).removeClass('menuHover');
});
});
</script>
</head>
<body>
<ul class="menu">
<li><a href="download.html">Download</a></li>
5.19 Writing Unobtrusive JavaScript | 127
<li><a href="documentation.html">Documentation</a></li>
<li><a href="tutorials.html">Tutorials</a></li>
</ul>
</body>
</html>
Ve`ve iemoveu the inline event hanuleis anu ieplaceu them with jQueiy event han-
uleis, sepaiating the content anu Lehavioi. Now il we want to auu moie menu items,
we uon`t have to copy anu paste the same Latch ol event hanuleis; insteau, the event
hanulei will automatically Le auueu.
Ve have also moveu the style iules loi the hovei ellect into a CSS class, sepaiating the
Lehavioi anu piesentation. Il we want to change the styling loi the hovei ellect latei,
we can just upuate the stylesheet insteau ol having to mouily the maikup.
Discussion
Vhile an all in one HTML lile with onevent attiiLutes woiks line in a small, simple
page, it uoesn`t scale up veiy well. As youi pages get moie complex, sepaiating pie-
sentation anu Lehavioi makes the coue easiei to maintain.
Ve uiun`t uo it in this simple example, Lut il you have multiple pages using the same
]avaSciipt oi CSS coue, move that coue to a common .js oi .css lile. That way it will
Le uownloaueu into the Liowsei cache once, insteau ol Leing ie-sent on eveiy page
loau. As a iesult, once one ol youi pages has Leen visiteu, the iest will loau lastei.
5.20 Using jQuery for Progressive Enhancement
Problem
You want to Luilu a site that allows simple task management with a gieat usei expeii-
ence using animations anu Ajax, Lut you also want to suppoit useis who have ]avaSciipt
uisaLleu.
Solution
You can Luilu the site to woik without all the llashiness anu then unoLtiusively auu
the ]avaSciipt lunctionality:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="en-us" />
<title>Task List</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js">
</script>
128 | Chapter 5:Faster, Simpler, More Fun
<script type="text/javascript">
$(document).ready( function() {
var url = $('form').attr('action');
$(':checkbox').click(function() {
$.post(url, this.name + '=1');
$(this).parent().slideUp(function() {
$(this).remove();
});
});
$(':submit').hide();
});
</script>
</head>
<body>
<form method="post" action="tasklist.html">
<ul>
<li>
<input type="checkbox" name="task1" id="task1" />
<label for="task1">Learn jQuery</label>
</li>
<li>
<input type="checkbox" name="task2" id="task2" />
<label for="task2">Learn Progressive Enhancement</label>
</li>
<li>
<input type="checkbox" name="task3" id="task3" />
<label for="task3">Build Great Websites</label>
</li>
</ul>
<input type="submit" value="Mark Complete" />
</form>
</body>
</html>
The input loim in this page uoesn`t ieguiie ]avaSciipt. The usei checks oll the tasks
he has completeu anu suLmits the loim, anu then it woulu Le up to the seivei to loau
a new page with the completeu tasks iemoveu liom the list.
Now, we can piogiessively enhance the page using jQueiy: we Linu an event hanulei
to the checkLoxes that mimics a stanuaiu loim suLmit, Ly getting the suLmit URL loi
the loim anu geneiating POST uata showing that the checkLox was checkeu. Then we
animate the iemoval ol the task to pioviue leeuLack to the usei. Ve also hiue the suLmit
Lutton Lecause maiking tasks complete has Lecome an instantaneous piocess.
Discussion
Although lew people Liowse without ]avaSciipt these uays, it`s still a goou piactice
when possiLle to Luilu youi pages so they woik line without ]avaSciipt anu then use
jQueiy anu ]avaSciipt to enhance them.
5.20 Using jQuery for Progressive Enhancement | 129
Bewaie that you uon`t make the usei expeiience worsc with ]avaSciipt
enhancements. The non-]avaSciipt veision ol this page may not give
immeuiate leeuLack when you check oll a task, Lut it uoes give you a
way to change youi minu easily il you make a mistake: eithei uncheck
it Leloie suLmitting oi just uon`t suLmit the loim at all.
Il you suLmit each checkLox immeuiately when it`s clickeu, Le suie
you pioviue a way loi youi visitoi to unuo that action. Il the task item
uisappeais liom the page, people will Le aliaiu to click loi leai ol clicking
the wiong item. You coulu eithei leave the item in the page Lut move it
to a completeu section oi auu an explicit Unuo option.
5.21 Making Your Pages Accessible
Problem
You`ie Luiluing a weL application with complex wiugets anu lots ol Ajax lunctionality,
Lut you want to accommouate visitois with uisaLilities.
Solution
Auu keyLoaiu accessiLility anu AccessiLle Rich Inteinet Applications (ARIA) semantics
to youi wiugets. In the lollowing coue, the changes to suppoit these leatuies aie inui-
cateu in bold:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="en-us" />
<title>Dialog Demo</title>
<style type="text/css">
table {
border-collapse: collapse;
width: 500px;
}
th, td {
border: 1px solid #000;
padding: 2px 5px;
}
.dialog {
position: absolute;
background-color: #fff;
border: 1px solid #000;
width: 400px;
padding: 10px;
}
.dialog h1 {
margin: 0 0 10px;
}
130 | Chapter 5:Faster, Simpler, More Fun
.dialog .close {
position: absolute;
top: 10px;
right: 10px;
}
</style>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js">
</script>
<script type="text/javascript">
$(document).ready( function() {
function close() {
dialog.hide();
$('#add-user').focus();
}
var title = $('<h1>Add User</h1>')
.attr('id', 'add-user-title'),
closeButton = $('<button>close</button>')
.addClass('close')
.click(close)
.appendTo(title),
content = $('<div/>')
.load('add.html'),
dialog = $('<div/>')
.attr({
role: 'dialog',
'aria-labelledby': 'add-user-title'
})
.addClass('dialog')
.keypress(function(event) {
if (event.keyCode == 27) {
close();
}
})
.append(title)
.append(content)
.hide()
.appendTo('body');
$('#add-user').click(function() {
var height = dialog.height(),
width = dialog.width();
dialog
.css({
top: ($(window).height() - height) / 2
+ $(document).scrollTop(),
left: ($(window).width() - width) / 2
5.21 Making Your Pages Accessible | 131
+ $(document).scrollLeft()
})
.show();
dialog.find('#username').focus();
return false;
});
});
</script>
</head>
<body>
<h1>Users</h1>
<a id="add-user" href="add.html">add a user</a>
<table>
<thead>
<tr>
<th>User</th>
<th>First Name</th>
<th>Last Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>jsmith</td>
<td>John</td>
<td>Smith</td>
</tr>
<tr>
<td>mrobertson</td>
<td>Mike</td>
<td>Robertson</td>
</tr>
<tr>
<td>arodriguez</td>
<td>Angela</td>
<td>Rodriguez</td>
</tr>
<tr>
<td>lsamseil</td>
<td>Lee</td>
<td>Samseil</td>
</tr>
<tr>
<td>lweick</td>
<td>Lauren</td>
<td>Weick</td>
</tr>
</tbody>
</table>
</body>
</html>
132 | Chapter 5:Faster, Simpler, More Fun
Ve`ve auueu seveial uselul leatuies with just a small amount ol auuitional coue:
Ve auueu ARIA semantics (role anu aria-labelledby) so that assistive technology
uevices such as scieen ieaueis know that oui <div> is a uialog anu not just auui-
tional content on the page.
Ve placeu the keyLoaiu locus in the uialog`s liist input lielu when it opens. This
is helplul loi all youi visitois, sighteu anu nonsighteu alike.
Ve moveu the keyLoaiu locus Lack to the Auu Useis link when the uialog closes.
Ve alloweu the uialog to Le canceleu with the Escape key.
Discussion
ARIA is a woik in piogiess, so Liowsei anu scieen ieauei suppoit loi it is still limiteu.
But Ly auuing it now, you`ll Le Lettei piepaieu loi those visitois who can use it. Anu
impioveu keyLoaiu access Lenelits all youi visitois.
Foi moie inloimation aLout ARIA, see the lollowing:
VAI-ARIA Oveiview
DHTML Style Guiue
Don`t Le thiown oll Ly the olu-school DHTML name; the DHTML Style
Guiue is an up-to-uate keyLoaiu accessiLility ieleience loi all the latest
wiugets.
5.21 Making Your Pages Accessible | 133
CHAPTER 6
Dimensions
Rcbccca Murphcy
6.0 Introduction
Dimensions aie a coie pait ol auuing auvanceu Lehaviois to a weLsite. Once you know
how to manipulate the uimensions ol elements anu theii position on the page, you will
have a new level ol contiol ovei youi usei inteilace, pioviuing uesktop-like Lehaviois
anu inteiactions in youi application.
6.1 Finding the Dimensions of the Window and Document
Problem
You want to get the wiuth anu height ol the winuow anu uocument in pixels.
Solution
jQueiy`s width anu height methous pioviue easy access to the Lasic uimensions ol the
winuow oi uocument:
jQuery(document).ready(function() {
alert('Window height: ' + jQuery(window).height()); // returns the height of
the viewport
alert('Window width: ' + jQuery(window).width()); // returns the width of the
viewport
alert('Document height: ' + jQuery(document).height()); // returns the height
of the document
alert('Document width: ' + jQuery(document).width()); // returns the width of
the document
});
135
Discussion
It`s impoitant to unueistanu that the wiuth anu height ol the uocument can (anu likely
will) Le uilleient liom the wiuth anu height ol the winuow. The uimensions ol the
winuow ielei to the size ol the viewpoitthat poition ol the Liowsei that is availaLle
loi uisplaying a uocument. The uimensions ol the uocument ielei to the size ol the
uocument itsell. In most cases, the uocument height will Le tallei than the winuow`s
height. The uocument`s wiuth will always Le at least the winuow`s wiuth Lut may Le
gieatei than the winuow`s wiuth. In Figuie 6-1, jQuery('body').width() < jQuery(docu
ment).width(), anu jQuery(document).width() == jQuery(window).width(). Il the Louy
weie wiuei than the winuow, the uocument wiuth woulu inciease accoiuingly.
Iigurc -1. Thc docuncnt sizc and thc window sizc arc ojtcn dijjcrcnt
The width anu height methous can also accept aiguments il you want to set the
uimensions ol an element. The aigument can Le pioviueu as an integeiin which case
it will Le inteipieteu as a pixel measuiementoi as a stiing, in which case it is intei-
pieteu as a CSS-like measuiement (i.e., $('#foo').width('300px')).
136 | Chapter 6:Dimensions
6.2 Finding the Dimensions of an Element
Problem
You want to ueteimine the space occupieu Ly an element.
Solution
The width anu height methous can Le applieu to any element, anu they aie uselul loi
ueteimining the computeu wiuth oi height ol an element. Howevei, they lall shoit il
you neeu to ueteimine the actual ieal estate that an element is occupying on the scieen.
In auuition to width anu height, jQueiy pioviues the lollowing methous loi ueteimining
moie specilic uimensions ol an element:
innerWidth
Retuins the wiuth cxc|uding the Loiuei anu inc|uding the pauuing
innerHeight
Retuins the height cxc|uding the Loiuei anu inc|uding the pauuing
outerWidth
Retuins the wiuth incluuing both the Loiuei and the pauuing
outerHeight
Retuins the height inc|uding the Loiuei anu inc|uding the pauuing
Foi a visual ieleience, see Figuie 6-2.
Iigurc -2. |||ustration oj an c|cncnt`s hcight, inncrHcight, and outcrHcight
6.2 Finding the Dimensions of an Element | 137
Given the lollowing HTML:
<div id="results"></div>
<div id="myDiv">Some text.</div>
anu the lollowing CSS:
#myDiv {
width:100px;
height:30px;
padding:10px;
border:1px;
}
you coulu expect the lollowing:
jQuery(document).ready(function() {
var $myDiv = jQuery('#myDiv');
var $results = jQuery('#results');
jQuery('<p>Computed width: ' + $myDiv.width() + '</p>')
.appendTo($results); // 100
jQuery('<p>Computed height: ' + $myDiv.height() + '</p>')
.appendTo($results); // 30
jQuery('<p>Inner width: ' + $myDiv.innerWidth() + '</p>')
.appendTo($results); // 120
jQuery('<p>Inner height: ' + $myDiv.innerHeight() + '</p>')
.appendTo($results); // 50
jQuery('<p>Outer width: ' + $myDiv.outerWidth() + '</p>')
.appendTo($results); // 122
jQuery('<p>Outer height: ' + $myDiv.outerHeight() + '</p>')
.appendTo($results); // 52
jQuery('<p>Document outer height: ' + jQuery(document).outerHeight() + '</p>')
.appendTo($results); // NaN
jQuery('<p>Document inner height: ' + jQuery(document).innerHeight() + '</p>')
.appendTo($results); // NaN
jQuery('<p>Window outer height: ' + jQuery(window).outerHeight() + '</p>')
.appendTo($results); // NaN
jQuery('<p>Window inner height: ' + jQuery(window).innerHeight() + '</p>')
.appendTo($results); // NaN
});
Discussion
The innerWidth/innerHeight anu outerWidth/outerHeight methous aie uselul tools loi
ueteimining the actual uimension that you`ie alteithe Lasic wiuth anu height meth-
ous aie ol limiteu use when you aie tiying to measuie the actual ieal estate that an
element with Loiuei anu pauuing occupies on the scieen.
Note that using innerWidth, innerHeight, outerWidth, oi outerHeight methous on
jQuery(document) oi jQuery(window) oLjects will ietuin NaN.
138 | Chapter 6:Dimensions
6.3 Finding the Offset of an Element
Problem
You want to ueteimine the location ol an element in the uocument.
Solution
jQueiy olleis thiee methous that aie uselul in ueteimining an element`s position:
offset
Retuins an oLject containing the position ol the top-lelt coinei ol the element
ielative to the uocument`s top-lelt coinei
position
Retuins an oLject containing the position ol the top-lelt coinei ol the element
ielative to the top-lelt coinei ol the liist positioneu paient ol the element (the
offsetParent)
offsetParent
Retuins a jQueiy oLject containing the offsetParent ol the element
The offset methou is uselul loi ueteimining the location ol an element on the page
loi example, il you want to scioll the winuow to an element. The position methou is
uselul loi iepositioning elements anu loi linuing the position ol an element in a sciolling
containei. Both tasks will Le uiscusseu in suLseguent sections; this section seeks to
seive as an oveiview to the positioning methous.
Given the lollowing HTML wheie the <body> element has 0-pixel maigin anu 10-pixel
pauuing:
<body id="the_offset_parent">
<h1>Finding the Offset of an Element</h1>
<div id="foo">
<div id="bar">Some text inside #bar, which is inside #foo</div>
</div>
<div id="results"></div>
</body>
you can use the lollowing coue to ueteimine the position, ollset, anu ollset paient ol
the two DIVs:
jQuery(document).ready(function() {
var $foo = jQuery('#foo');
var $bar = jQuery('#bar');
var $results = jQuery('#results');
var fooPosition = $foo.position();
var barPosition = $bar.position();
var fooOffset = $foo.offset();
var barOffset = $bar.offset();
6.3 Finding the Offset of an Element | 139
var $fooOffsetParent = $foo.offsetParent();
var $barOffsetParent = $bar.offsetParent();
$results
.append('<p>#foo position.top: ' + fooPosition.top + '</p>') // 10
.append('<p>#foo position.left: ' + fooPosition.left + '</p>') // 10
.append('<p>#bar position.top: ' + barPosition.top + '</p>') // 10
.append('<p>#bar position.left: ' + barPosition.left + '</p>') // 10
.append('<p>#foo offset.top: ' + fooOffset.top + '</p>') // 10
.append('<p>#foo offset.left: ' + fooOffset.left + '</p>') // 10
.append('<p>#bar offset.top: ' + barOffset.top + '</p>') // 10
.append('<p>#bar offset.left: ' + barOffset.left + '</p>') // 10
.append('<p>ID of #foo offsetParent: '
+ $fooOffsetParent.attr('id')) // the_offset_parent
.append('<p>ID of #bar offsetParent: '
+ $barOffsetParent.attr('id')); // the_offset_parent
});
In this case, Loth elements have the same position, anu Loth have the same
offsetParent (the uocument`s <body> element).
Howevei, il #foo is positioneu using CSS:
<body id="the_offset_parent">
<div id="foo" style="position:absolute; top:10px; left:10px;">
<div id="bar">Some text inside #bar, which is inside the
absolutely-positioned #foo</div>
</div>
<div id="results" style="position:absolute; top:60px; left:10px;"></div>
</body>
then the iesults change. The #foo DIV hasn`t actually moveu anu its offsetParent hasn`t
changeu, so its position anu ollset stay the same; the #bar DIV hasn`t moveu eithei, Lut
since its offsetParent has changeu, its position has changeuiememLei, an element`s
position is ielative to its ollset paient.
jQuery(document).ready(function() {
var $foo = jQuery('#foo');
var $bar = jQuery('#bar');
var $results = jQuery('#results');
var fooPosition = $foo.position();
var barPosition = $bar.position();
var fooOffset = $foo.offset();
var barOffset = $bar.offset();
var $fooOffsetParent = $foo.offsetParent();
var $barOffsetParent = $bar.offsetParent();
$results
.append('<p>#foo position.top: ' + fooPosition.top + '</p>') // 10
.append('<p>#foo position.left: ' + fooPosition.left + '</p>') // 10
140 | Chapter 6:Dimensions
.append('<p>#bar position.top: ' + barPosition.top + '</p>') // 0
.append('<p>#bar position.left: ' + barPosition.left + '</p>') // 0
.append('<p>#foo offset.top: ' + fooOffset.top + '</p>') // 10
.append('<p>#foo offset.left: ' + fooOffset.left + '</p>') // 10
.append('<p>#bar offset.top: ' + barOffset.top + '</p>') // 10
.append('<p>#bar offset.left: ' + barOffset.left + '</p>') // 10
.append('<p>ID of #foo offsetParent: '
+ $fooOffsetParent.attr('id')) // the_offset_parent
.append('<p>ID of #bar offsetParent: '
+ $barOffsetParent.attr('id')); // foo
});
Discussion
The impoitant thing to iememLei is this: the offset methou will always give you an
element`s position ielative to the uocument. The ietuin value ol the position methou
nay Le the element`s position ielative to the uocument, uepenuing on whethei the
element has an offsetParent. Il the element has an offsetParentthat is, a paient
element that has positioning applieu to itthen the position methou will pioviue in-
loimation aLout the position ol the element ielative to the offsetParent, not to the
uocument.
jQueiy`s offsetParent methou pioviues a ieplacement loi the stanuaiu
]avaSciipt offsetParent DOM noue piopeity. In ceitain casessuch as
when an element has a lixeu positionsome Liowseis will ietuin null
when askeu loi the offsetParent piopeity ol the element.
6.4 Scrolling an Element into View
Problem
You want to scioll the uocument oi an element to Liing anothei element into view.
Solution: Scrolling the Whole Window
Il you neeu to scioll the whole winuow, you`ll use the offset methou to ueteimine
the location ol the uestination element ielative to the uocument anu then use the
scrollTop methou to scioll the uocument to Liing the element into view.
Foi example, let`s say you want to scioll to the #foo element when the usei clicks the
#bar element:
jQuery('#bar').click(function() {
var fooOffset = jQuery('#foo').offset(),
destination = fooOffset.top;
jQuery(document).scrollTop(destination);
});
6.4 Scrolling an Element into View | 141
Solution: Scrolling Inside an Element
Il youi uestination element is insiue a sciolling containei, you`ll use the position meth-
ou to ueteimine the location ol the uestination element ielative to the containei, auu
it to the cuiient scioll position ol the containei, anu then use the scrollTop methou to
scioll the containei to Liing the element into view. Note that the sciolling containei
must Le positioneuusing position: relative, position: absolute, oi position:
fixedin oiuei loi this to woik.
Foi example, consiuei the lollowing maikup, styleu so that #foo is not laige enough to
show Loth paiagiaphs at once.
<head>
<style>
#foo {
width:300px;
padding:10px;
height:20px;
border:1px solid black;
overflow:auto;
position:relative;
}
</style>
</head>
<body>
<input type="button" id="bar" value="Click to scroll to last paragraph" />
<input type="button" id="bam" value="Click to scroll to last paragraph with
animation" />
<div id="foo">
<p>This is the first paragraph. Lorem ipsum dolor sit amet, consectetur
adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim
id est laborum.</p>
<p>This is the second paragraph. Lorem ipsum dolor sit amet, consectetur
adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim
id est laborum.</p>
<!-- several more paragraphs -->
</div>
</body>
Sciolling #foo to show the last paiagiaph is simple:
var $foo = jQuery('#foo');
$('#bar').click(function() {
var lastParagraphPosition = jQuery('#foo p:last').position();
var scrollPosition = $foo.scrollTop() + lastParagraphPosition.top;
$foo.scrollTop(scrollPosition);
});
142 | Chapter 6:Dimensions
In Loth ol these examples, the sciolling happens instantaneouslyellicient, Lut not
necessaiily attiactive. The animate methou will animate an element`s scrollTop piop-
eity, so animating the tiansition is tiivial. Heie`s how we woulu uo it loi the sciolling
containei:
var $foo = jQuery('#foo');
$('#bam').click(function() {
var lastParagraphPosition = jQuery('#foo p:last').position();
var scrollPosition = $foo.scrollTop() + lastParagraphPosition.top;
jQuery('#foo').animate({scrollTop: scrollPosition}, 300);
});
jQueiy also incluues a scrollLeft methou, with Lehavioi analogous to
scrollTop.
6.5 Determining Whether an Element Is Within the Viewport
Problem
You want to ueteimine whethei an element is visiLle within the viewpoit; luithei, you
want to ueteimine the peicentage ol the element that is visiLle anu scioll to it il it is
less than 50 peicent visiLle.
Solution
This makes use ol seveial ol the methous uiscusseu in eailiei sections ol this chaptei.
Theie aie seveial steps to this piocess:
1. Deteimine the size ol the viewpoit.
2. Deteimine the scioll position ol the uocument.
3. Figuie out the minimum anu maximum values loi the top anu lelt positions ol the
element il the element is visiLle.
+. Test the position ol the element against those values.
jQuery(document).ready(function() {
var viewportWidth = jQuery(window).width(),
viewportHeight = jQuery(window).height(),
documentScrollTop = jQuery(document).scrollTop(),
documentScrollLeft = jQuery(document).scrollLeft(),
minTop = documentScrollTop,
maxTop = documentScrollTop + viewportHeight,
minLeft = documentScrollLeft,
maxLeft = documentScrollLeft + viewportWidth,
6.5 Determining Whether an Element Is Within the Viewport | 143
$myElement = jQuery('#myElement'),
elementOffset = $myElement.offset();
if (
(elementOffset.top > minTop && elementOffset.top < maxTop) &&
(elementOffset.left > minLeft &&elementOffset.left < maxLeft)
) {
alert('element is visible');
} else {
alert('element is not visible');
}
});
Vith this solution, we know whethei the top ol the element is visiLle in the viewpoit;
a Lettei solution woulu test whethei the entiie element was containeu in the viewpoit:
jQuery(document).ready(function() {
var viewportWidth = jQuery(window).width(),
viewportHeight = jQuery(window).height(),
documentScrollTop = jQuery(document).scrollTop(),
documentScrollLeft = jQuery(document).scrollLeft(),
$myElement = jQuery('#myElement'),
elementOffset = $myElement.offset(),
elementHeight = $myElement.height(),
elementWidth = $myElement.width(),
minTop = documentScrollTop,
maxTop = documentScrollTop + viewportHeight,
minLeft = documentScrollLeft,
maxLeft = documentScrollLeft + viewportWidth;
if (
(elementOffset.top > minTop && elementOffset.top + elementHeight < maxTop) &&
(elementOffset.left > minLeft && elementOffset.left + elementWidth < maxLeft)
) {
alert('entire element is visible');
} else {
alert('entire element is not visible');
}
});
Alteinatively, we coulu look at how much ol the element is visiLleil it is less than a
ceitain amount, then we can scioll to the element:
jQuery(document).ready(function() {
var viewportWidth = jQuery(window).width(),
viewportHeight = jQuery(window).height(),
documentScrollTop = jQuery(document).scrollTop(),
documentScrollLeft = jQuery(document).scrollLeft(),
$myElement = jQuery('#myElement'),
verticalVisible, horizontalVisible,
144 | Chapter 6:Dimensions
elementOffset = $myElement.offset(),
elementHeight = $myElement.height(),
elementWidth = $myElement.width(),
minTop = documentScrollTop,
maxTop = documentScrollTop + viewportHeight,
minLeft = documentScrollLeft,
maxLeft = documentScrollLeft + viewportWidth;
function scrollToPosition(position) {
jQuery('html,body').animate({
scrollTop : position.top,
scrollLeft : position.left
}, 300);
}
if (
((elementOffset.top > minTop && elementOffset.top < maxTop) ||
(elementOffset.top + elementHeight > minTop && elementOffset.top +
elementHeight < maxTop))
&&
((elementOffset.left > minLeft && elementOffset.left < maxLeft) ||
(elementOffset.left + elementWidth > minLeft && elementOffset.left +
elementWidth < maxLeft))
) {
alert('some portion of the element is visible');
if (elementOffset.top >= minTop && elementOffset.top + elementHeight
<= maxTop) {
verticalVisible = elementHeight;
} else if (elementOffset.top < minTop) {
verticalVisible = elementHeight - (minTop - elementOffset.top);
} else {
verticalVisible = maxTop - elementOffset.top;
}
if (elementOffset.left >= minLeft && elementOffset.left + elementWidth
<= maxLeft) {
horizontalVisible = elementWidth;
} else if (elementOffset.left < minLeft) {
horizontalVisible = elementWidth - (minLeft - elementOffset.left);
} else {
horizontalVisible = maxLeft - elementOffset.left;
}
var percentVerticalVisible = (verticalVisible / elementHeight) * 100;
var percentHorizontalVisible = (horizontalVisible / elementWidth) * 100;
if (percentVerticalVisible < 50 || percentHorizontalVisible < 50) {
alert('less than 50% of element visible; scrolling');
scrollToPosition(elementOffset);
} else {
alert('enough of the element is visible that there is no need to scroll');
}
6.5 Determining Whether an Element Is Within the Viewport | 145
} else {
// element is not visible; scroll to it
alert('element is not visible; scrolling');
scrollToPosition(elementOffset);
}
});
The sciollTo plugin Ly Aiiel Fleslei pioviues excellent shoithanu access
to many ol these methous Ly allowing you to simply wiite
$.scrollTo('#myElement'); it takes caie ol ueteimining the position ol
the uestination element.
6.6 Centering an Element Within the Viewport
Problem
You want to scioll the winuow to centei an element within the viewpoit.
Solution
Get the viewpoit`s uimensions; ueteimine the wiuth, height, anu ollset ol the element;
anu use a little math to centei the element in the viewpoit:
jQuery(document).ready(function() {
jQuery('#bar').click(function() {
var viewportWidth = jQuery(window).width(),
viewportHeight = jQuery(window).height(),
$foo = jQuery('#foo'),
elWidth = $foo.width(),
elHeight = $foo.height(),
elOffset = $foo.offset();
jQuery(window)
.scrollTop(elOffset.top + (elHeight/2) - (viewportHeight/2))
.scrollLeft(elOffset.left + (elWidth/2) - (viewportWidth/2));
});
});
In the linal lines, we auu the top ollset ol the element to hall the element`s height in
oiuei to ueteimine the veitical centei ol the element. Then we suLtiact hall the view-
poit`s height to ueteimine the position to which we want the winuow to scioll. Finally,
we uo an analogous calculation to centei the viewpoit hoiizontally.
146 | Chapter 6:Dimensions
6.7 Absolutely Positioning an Element at Its Current Position
Problem
You want to tuin a static oi ielatively positioneu element into Leing aLsolutely
positioneu.
Solution
To accomplish this, we simply get the position ol the element anu then use it to set the
element`s CSS piopeities accoiuingly:
var $myElement = jQuery('#foo p').eq(0),
elPosition = $myElement.position();
$myElement.css({
position : 'absolute',
top : elPosition.top,
left : elPosition.left
});
Ve can also easily ieposition an element ielative to its cuiient position:
var $myElement = jQuery('#foo p').eq(1),
elPosition = $myElement.position();
$myElement.css({
position : 'absolute',
top : elPosition.top + 20,
left : elPosition.left + 20
});
6.8 Positioning an Element Relative to Another Element
Problem
You want to position a new element ielative to an existing element.
Solution
Get the wiuth, height, anu ollset ol the existing element, anu use the values to position
the new element accoiuingly.
Given the lollowing HTML:
<style>
#foo {
width: 300px;
height: 100px;
border: 1px solid red;
padding: 5px;
}
6.8 Positioning an Element Relative to Another Element | 147
#tooltip {
border: 1px solid black;
padding: 5px;
background-color: #fff;
</style>
<div id="foo">An existing element</div>
the lollowing coue woulu auu an element as a siLling to the existing element Lut posi-
tioneu insiue the element, 10 pixels liom the top anu 10 pixels liom the lelt ol the
existing element`s top-lelt coinei, anu with a wiuth 20 pixels less than that ol the
existing element:
jQuery(document).ready(function() {
var $foo = jQuery('#foo'),
fooPosition = $foo.position(),
$tooltip = $('<div id="tooltip">A new element</div>').insertAfter($foo);
$tooltip.css({
position : 'absolute',
top : fooPosition.top + 10,
left : fooPosition.left + 10,
width : $foo.width() - 20
});
});
Il you wanteu to auu the new element somewheie else in the pagethat is, il you uiun`t
want it to Le a siLling ol the existing elementyou coulu aujust youi coue to look at
the ollset ol the oiiginal element iathei than the position:
jQuery(document).ready(function() {
var $foo = jQuery('#foo'),
fooOffset = $foo.offset(),
$tooltip = $('<div id="tooltip">A new element</div>').appendTo('body');
$tooltip.css({
position : 'absolute',
top : fooOffset.top + 10,
left : fooOffset.left + ($foo.width() / 2),
width : $foo.width() - 20
});
});
6.9 Switching Stylesheets Based on Browser Width
Problem
You want to change the uocument`s CSS Laseu on the wiuth ol the Liowsei.
148 | Chapter 6:Dimensions
Solutions
Theie aie a lew solutions to this pioLlem. One changes the class attiiLute ol the Louy
element, anothei changes the href attiiLute ol the stylesheet you want to change, anu
the thiiu incluues all size-ielateu stylesheets on the page Lut enaLles only one ol them
at a time.
In each case, we`ll cieate a lunction that checks the wiuth ol the Liowsei anu Linu that
lunction to the uocument`s ready event anu to the winuow`s resize event. The
checkWidth lunction will then call the setSize lunction, which we`ll ueline Laseu on the
appioach we`ie taking:
var checkWidth = function() {
var browserWidth = $(window).width();
if (browserWidth < 960) {
setSize('small');
} else {
setSize('large');
}
};
jQuery(document).ready(function() {
checkWidth();
$(window).resize(checkWidth);
});
The uelinition ol the setSize lunction uepenus on how you want to switch styles.
Solution 1: Changing the Class on the Body Element
var setSize = function(size) {
var $body = jQuery('body');
jQuery('body').removeClass('large small').addClass(size);
};
Solution 2: Changing the href Attribute of the Stylesheet Thats Responsible
for Size-Related Styling
Let`s assume you have the lollowing size-ielateu stylesheet in youi uocument:
<link rel="stylesheet" type="text/css" id="css_size" href="size-small.css" />
In this case, you woulu ueline the setSize lunction as lollows:
var setSize = function(size) {
var $css = jQuery('#css_size');
$css.attr('href', 'size-' + size + '.css');
};
Note that in this case, the new CSS lile is ieguesteu liom the seivei, which is likely to
cause a Liiel uelay in the style change occuiiing. Foi this ieason, this is peihaps the
least-pieleiaLle methou.
6.9 Switching Stylesheets Based on Browser Width | 149
Solution 3: Include All Size-Related Stylesheets in the Page, but Enable Only
One at a Time
<link rel="stylesheet" type="text/css" class="css_size small" href="size-small.css" />
<link rel="alternate stylesheet" type="text/css" class="css_size large"
href="size-large.css" disabled=true/>
In this case, you woulu ueline the setSize lunction as lollows:
var setSize = function(size) {
jQuery('link.css_size').each(function() {
var $this = $(this);
if ($this.hasClass(size)) {
$this
.removeAttr('disabled')
.attr('rel', 'stylesheet');
} else {
$this
.attr('disabled', true)
.attr('rel', 'alternate stylesheet');
}
});
};
In this appioach, all stylesheets aie loaueu at page loau, anu nothing new is letcheu
when switching liom one stylesheet to anothei. This eliminates the uelay causeu Ly
solution 2 Lut it also iesults in potentially unnecessaiy HTTP ieguests il youi usei is
unlikely to neeu the alteinate stylesheets.
Discussion
Theie is no uelinitive answei to which ol the thiee style-switching methous is the Lest.
Vhen choosing a methou, you`ll want to consiuei how likely youi useis aie to neeu a
uilleient stylesheet, how Lig youi size-ielateu stylesheets aie, anu how you pielei to
manage youi size-ielateu styles. In many cases, the methou liom the liist solution will
Le Loth sullicient anu pieleiaLle.
150 | Chapter 6:Dimensions
CHAPTER 7
Effects
Rcmy Sharp
7.0 Introduction
Out ol the Lox, jQueiy comes with a numLei ol pieset ellects anu the ioLust low-level
animation methou loi cieating youi own custom ellects.
The pieset ellects incluue the lollowing:
Hiuing anu showing elements in a toggle lashion
Scaling anu simultaneously lauing elements in anu out ol view
Sliuing up anu uown anu toggling
Fauing in anu out anu to a specilic opacity
All ol the pieset ellects suppoit speeus anu callLack lunctions to tiiggei upon
completion.
In auuition to these pieuelineu ellects, theie aie also a numLei ol utilities that can help
you take moie contiol ovei youi animations:
:animated selectoi to assess whethei an element is in the piocess ol Leing animateu
The aLility to tuin oll anu on all ellects acioss the Loaiu
The aLility to auu to the animation gueue with youi own Lespoke lunctions
Function to change the entiie gueue ol animations
It`s woith noting that the canneu animation methous, hide (with a uu-
iation) anu slideUp, ieuuce the maigin anu pauuing on the element as
they appioach zeio height. This may allect how you want to maik up
the page anu CSS loi youi ellect. Also note that jQueiy uoesn`t ojjicia|-
|y suppoit ellects in uocuments using QuiiksMoue.
151
Animate Method
Using the animate methou gives you complete contiol ovei the animation to ioll youi
own Lespoke ellect. Using the animate methou, you can uo the lollowing:
Contiol CSS piopeities (limiteu to numeiical piopeities only)
Contiol scrollTop anu scrollLeft DOM piopeities (il the element has oveillow)
Use any CSS unit ol measuie, e.g., pixels, ems, inches, oi peicentages loi the enu
point values
Specily the enu point ol the ellect as a lixeu value oi a ielative value liom the
element`s cuiient state
Use toggle as a value to llip Letween states, e.g., opacity: toggle
Specily an easing methou to iun the animation ovei
Set callLacks at all points ol the animation: on each step ol the animation anu when
it linishes
Specily whethei the animation shoulu gueue oi iun immeuiately allowing loi
simultaneous animations
Vhen specilying piopeities to animate, they must Le wiitten using
camel case, e.g. marginLeft iathei than margin-left. Il you uon`t uo it
this way, nothing will animate!
Animation Speeds
The speed paiametei can Le specilieu using eithei milliseconus oi a lew pieuelineu
stiings:
slow has a value ol 600 milliseconus.
fast has a value ol 200 milliseconus.
Il a speeu isn`t explicitly passeu in to the animation lunctions, the animation will iun
at a uelault speeu ol +00 milliseconus.
Il you explicitly pass in a speeu ol zeio, then the animation will iun like
the .css() lunction, Lut as ol jQueiy 1.3, the methou call will iun syn-
chronous|y iathei than asynchronous|y like all othei animations woulu
uo.
Effects Template
Unless otheiwise stateu in the iecipe, we will use the lollowing template loi all the
examples, applying a uilleient jQueiy snippet loi each solution:
152 | Chapter 7:Effects
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Chapter 6</title>
<link rel="stylesheet" href="chapter6.css" type="text/css" />
<script src="jquery-latest.js" type="text/javascript"></script>
</head>
<body id="single">
<input type="button" id="animate" value="animate" />
<div class="box">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
</body>
</html>
All the inuiviuual examples aie availaLle online at http://jqucry-coo|boo|.con/cxan
p|cs/0/, incluuing a complete amalgamateu veision ol the iecipes.
7.1 Sliding and Fading Elements in and out of View
Problem
Ve want to ieveal oi toggle a Llock ol content into view. This can Le tiiggeieu Ly the
usei clicking some element oi can Le liieu Ly some othei event.
Rathei than just showing anu hiuing, which coulu Le jaiiing visually, we want to cieate
a giauual ellect to ieveal the content into view.
Foi these solutions, I`ve assumeu we want to allow the usei to toggle the ellect.
Solution
Foi ieleience, il we weie just to show the element, oui coue woulu Le as lollows:
$(document).ready(function () {
$('#animate').click(function () {
$('.box').show();
});
);
Il we weie to togg|c the Lox Lut just toggle liom visiLle anu hiuuen, we woulu use the
lollowing insteau ol .show():
$('.box').toggle();
Howevei, oui solution wants to Le a little moie visually engaging than just toggling the
uisplay piopeity. So, let`s look at using the sliue anu laue methous:
7.1 Sliding and Fading Elements in and out of View | 153
Slide
$(document).ready(function () {
$('#animate').click(function () {
$('.box').slideToggle('slow');
});
});
Fade
Because theie`s no opacity toggle lunction, eithei we can use a comLination ol
fadeIn anu fadeOut:
$(document).ready(function () {
$('#animate').click(function () {
var $box = $('.box');
if ($box.is(':visible')) {
$box.fadeOut('slow');
} else {
$box.fadeIn('slow');
}
});
});
oi we can cieate oui own laue toggle animation, using the fadeTo methou:
$(document).ready(function () {
$('#animate').click(function () {
$('.box').fadeTo('slow', 'toggle');
});
});
Howevei, I`m ol the opinion that it ieaus Lettei loi lutuie maintenance il we use the
animate methou:
$(document).ready(function () {
$('#animate').click(function () {
$('.box').animate({ opacity : 'toggle' }, 'slow');
});
});
Both
Il we want to toggle the height anu opacity togethei, we can ieuse the pievious
solution anu auu the height to toggle at the same time. This woulu cause the Lox to
laue out and sliue up at the same time:
$(document).ready(function () {
$('#animate').click(function () {
$('.box').animate({
opacity : 'toggle',
height: 'toggle'
}, 'slow');
});
});
154 | Chapter 7:Effects
Discussion
As we can see liom the pievious solutions, the sliue anu laue methous aie the next step
up liom the stiaight show (anu hiue) anu toggle methous. The sliue methous come in
the lollowing llavois:
slideUp
slideDown
slideToggle
The laue methous uon`t have an explicit toggle leatuie, Lut it can Le achieveu. Fauing
has the lollowing methous:
fadeIn
fadeOut
fadeTo
Vith the exception ol fadeTo, all these methous take speed as the liist paiametei anu
a ca||bac| junction as the seconuLoth ol which aie optional. The callLack lunction
is executeu once the animation is complete, anu the context is set to the element the
animation ian against; i.e., the this vaiiaLle is the cuiient element.
The ieason I woulu choose to use animate ovei fadeTo to toggle opacity is that the
fadeTo paiameteis ieau the wiong way aiounu. Il a new uevelopei weie coming to the
coue, using the animate lunction almost ieaus as plain English, theieloie making it
easiei to skim anu unueistanu what is happening in the coue.
It`s woith also auuing that il you use the show (oi hide) methou using a speeu, it will
animate the height, wiuth, opacity, maigin, anu pauuing all in one animation, as shown
in Figuie 7-1.
Iigurc 7-1. Passing a spccd in to thc show ncthod aninatcs hcight, width, padding, nargin, and
opacity
7.1 Sliding and Fading Elements in and out of View | 155
7.2 Making Elements Visible by Sliding Them Up
Problem
You want to sliue the content Llock into view, Lut the UI uesign uictates that the content
must sliue upward when Leing ievealeu. The slideUp methou woulu hiue the element,
ieuucing the height liom the top position.
To sliue upwaiu, we neeu to use CSS to position the element anu then consiuei the
content that we aie ievealing.
Solution
HTML
Ve neeu to aLsolutely position the element we aie animating to get it to stic| to the
Lottom position so it can animate upwaiu when ievealing.
To achieve this, we neeu to wiap the animating element in anothei <div> (oi the element
that suits youi uesign) anu give it a position: relative style. (This may also Le
position: absolute. Ve just neeu a uelineu position to tiiggei the position: abso
lute on #revealUp to position ielatively to; howevei, since we want the uocument to
llow norna||y, we`ve useu position: relative.)
<div class="box">
<div id="revealUp">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
</div>
CSS
Now we neeu to give the box element a ielative position so that we can aLsolutely
position #revealUp ielative to it:
.box {
position: relative;
}
#revealUp {
position: absolute;
overflow: hidden;
display: none;
bottom: 0;
background-color: #c00;
height: 0;
}
156 | Chapter 7:Effects
jQuery
Ve can toggle the #revealUp Laseu on the element`s height. Ve`ie going to longei
lengths to animate the height upwaiu (Ly checking the cuiient height) iathei than just
using slideToggle()Lut we`ll look at why in the uiscussion:
$(document).ready(function () {
$('#animate').click(function () {
var $box = $('#revealUp');
if ($box.height() > 0) {
$box.animate({ height : 0 });
} else {
$box.animate({ height : '100%' });
}
});
});
Discussion
This solution ieguiies that we check the height ol the Lox to then ueteimine how we
pioceeu.
Notice how we uon`t use slideToggle, which Lehinu the scenes is veiy similai, il not
the same as, using .animate({ height: 'toggle' }).
The ieason we`ie not using the toggle is that loi the toggle to woik coiiectly, it neeus
to captuie the rca| height liom somewheie. As the element staits with a height ol zeio,
jQueiy has no way to woik out what the lull height is. Il we useu slideToggle, the
#revealUp element appeais Liielly as a 1-pixel slithei anu then uisappeais again. This
is Lecause theie`s no ieal height to animate to.
Insteau, we ueteimine whethei the height is gieat than zeio anu then animate the
height accoiuingly. Since the element is nesteu within anothei element with
position: relative, we can give it a height ol 100 peicent, anu it will giow to lill the
space.
In the iecipe, I have useu overflow: hidden. Howevei, il the lont size is
incieaseu Ly the usei, my example hiues some ol the content. In youi
ieal solutions, make suie you test that the content is still availaLle when
the lont size is incieaseu, anu consiuei eithei ensuiing that the ievealing
Lox is laige enough loi the content oi using overflow: auto on the
#revealUp element.
7.3 Creating a Horizontal Accordion
Problem
The jQueiy UI liLiaiy suppoits veitical accoiuions out ol the Lox, anu in lact theie aie
a lew simple coue snippets that can Le useu to cieate a iuuimentaiy accoiuion ellect.
7.3 Creating a Horizontal Accordion | 157
Howevei, making the accoiuion iun hoiizontally ieguiies specilic CSS anu a slightly
uilleient take on the jQueiy coue.
Foi this solution we won`t Le using the template, Lecause the maikup is uilleient loi
the hoiizontal accoiuion.
Solution
HTML
<div id="accordionWrapper">
<h3 class="red"><a href="#red">Red</a></h3>
<div id="red" class="box"><p>Lorem ipsum dolor sit amet, consectetur
adipisicing.</p></div>
<h3 class="green"><a href="#green">Green</a></h3>
<div id="green" class="box"><p>Lorem ipsum dolor sit amet, consectetur
adipisicing.</p></div>
<h3 class="blue"><a href="#blue">Blue</a></h3>
<div id="blue" class="box"><p>Lorem ipsum dolor sit amet, consectetur
adipisicing.</p></div>
</div>
CSS
#accordionWrapper {
margin: 10px;
}
#accordionWrapper h3 a {
text-indent: -9999px;
height: 150px;
width: 50px;
float: left;
}
#accordionWrapper .red {
background: #c00 url(images/red.png) no-repeat;
}
#accordionWrapper .green {
background: #0c0 url(images/green.png) no-repeat;
}
#accordionWrapper .blue {
background: #00c url(images/blue.png) no-repeat;
}
#accordionWrapper div.box {
float: left;
height: 150px;
width: 150px;
border: 0;
158 | Chapter 7:Effects
margin: 0;
/* to cancel the image from .red, etc */
background-image: none;
}
jQuery
$.fn.horizontalAccordion = function (speed) {
return this.each(function () {
var $accordionHeaders = $(this).find('h3'),
$open = $accordionHeaders.next().filter(':first'),
width = $open.outerWidth();
// initialize the display
$accordionHeaders.next().filter(':not(:first)').css({ display : 'none', width : 0
});
$accordionHeaders.click(function () {
if ($open.prev().get(0) == this) {
return;
}
$open.animate({ width: 0 }, { duration : speed });
$open = $(this).next().animate({ width : width }, { duration : speed });
});
});
};
$(document).ready(function () {
$('#accordionWrapper').horizontalAccordion(200);
});
Discussion
The HTML anu CSS lay the accoiuion out so that the elements within it aie all lloateu
to the lelt. Il you useu this on a weL page, you woulu pioLaLly expect to have to auu
a cleaiing element uiiectly altei the accoiuion to allow the lollowing content to llow
piopeily.
By lloating the elements to the lelt, oui accoiuion is set up with the h3 > a as the title
to the content panel.
Il CSS anu ]avaSciipt aie uisaLleu, then the content llows coiiectly anu is ieauaLle Ly,
loi instance, Google`s seaich engine.
Il CSS is tuineu on Lut ]avaSciipt isn`t, the uelault view is to see all the content panels.
Using jQueiy, we initialize the uisplay Ly hiuing all the panels except the liist, anu we
hook click hanuleis to the heaueis to sliue the content in anu out ol view.
The hoiizontal accoiuion has Leen wiitten as a jQueiy plugin, in paiticulai to show
that we uon`t neeu to haiu-coue any vaiiaLles within the accoiuion ellect. Ve only
7.3 Creating a Horizontal Accordion | 159
pass the uuiation speeu vaiiaLle in to the plugin, which ueteimines the uuiation ol the
ellect. Ve coulu easily upgiaue this plugin to also take an easing oi callLack.
It`s impoitant to note that thioughout this coue, all the click hanuling anu navigation
ol the DOM happens aiounu the <h3> element, not the <a> element. This still woiks,
keeping the coue ielatively simple (insteau ol having to navigate up anu uown liom the
<a> element to get the paient <h3> then the aujacent <div> element), Lut moie impoi-
tantly, olleis keyLoaiu accessiLility Lecause the <a> elements can Le taLLeu on to anu
tiiggeieu via the keyLoaiu. Ve uon`t have to Linu the click hanulei to the <a> element,
Lecause when the <a> element has the click event tiiggeieu (via clicking oi the key-
Loaiu), it bubb|cs up thiough the DOM anu is caught Ly oui click hanulei on the
<h3> element.
The plugin liist collects the necessaiy paits ol the accoiuion: the heauei, which will Le
clickaLle; the liist visiLle panel, anu the wiuth ol the panels (note that this veision ol
the plugin woiks only loi egual sizeu panels):
var $accordionHeaders = $(this).find('h3'),
this is the cuiient accoiuion wiappei element, typically a <div>.
Fiom the accoiuion wiappei, oui coue collects all the <h3> elements. Note that we will
make use ol next() anu prev() to change oui DOM collection liom the <h3> to the next
noues in the DOM tiee, in paiticulai the accoiuion content panels:
$open = $accordionHeaders.next().filter(':first'),
$open is a tempoiaiy vaiiaLle that will point to the cuiient visiLle panel. Ve can`t
use .is(':visible') Lecause we`ie actually ieuucing the wiuth anu the panel still has
a CSS piopeity ol display: block. So, we will keep tiack ol the cuiient panel thiough
this $open vaiiaLle:
width = $open.outerWidth();
Finally in the initialization, we captuie the wiuth ol the open panel so that we can
animate the wiuth ol the panels coiiectly.
Two tasks aie lelt:
Initialize the view ol panels, showing only the liist panel
Binu the click hanules to show anu hiue the panels
To initialize the view, we must hiue all the panels except the liist. Ve must also set the
wiuth to zeio to allow loi the animate lunction to inciease the wiuth, iathei than making
it pop out when it is shown.
To achieve this, we use an inveise liltei liom the $open vaiiaLle, in paiticu-
lai :not(:first):
$accordionHeaders.next().filter(':not(:first)').css({ display : 'none', width : 0 });
160 | Chapter 7:Effects
Once we have oui selection ol panels that aie not thc jirst, we change the CSS piopeities
to initialize them.
Finally, we attach the click hanulei.
RememLeiing that the $accordionHeaders vaiiaLle contains the h3 elements, the liist
thing we uo is say this: il the <h3> clickeu is the same as the cuiiently open panel, then
uon`t uo anything.
Since the $open vaiiaLle is the panel, we use .prev() to navigate to the pievious <h3>
element anu test whethei it matches the cuiient context ol the clickeu element.
Il the clickeu element is not the cuiient open panel, we animate the $open panel wiuth
to zeio, anu the cuiient clickeu panel to the captuieu wiuth.
Notice the veiy last line ol the click hanulei:
$open = $(this).next().animate({ width : width }, { duration : speed });
Because jQueiy usually ietuins jQueiy (except when getting a value) anu we`ie ani-
mating the panel that will now Le open, we can captuie this at the same time in the
$open vaiiaLle, thus oveiwiiting it with the latest panel.
7.4 Simultaneously Sliding and Fading Elements
Vhen some pait ol the weL page is hiuuen anu is shown to the usei only on a specilic
action, sometimes a simple show/hiue isn`t enough. Ve want to cieate moie pleasing
ellects loi oui visitois.
Depenuing on the layout ol the page, an instant show/hiue ellect may not make it
entiiely cleai to the visitoi what content was ievealeu. This is anothei auvantage ol
sliuing an element into view Lecause it gives a visual cue to the visitoi wheie the page
layout is changing.
Ve coulu use jQueiy`s Luilt-in show methou with a uuiation Lecause this a|nost uoes
the joL, Lut not guite Lecause it also animates the wiuth ol the element, as shown eailiei
in Figuie 7-1. As you also noteu eailiei, the show methou will animate any pauuing
anu maigin aiounu the element, so to solve the pioLlem we will use the animate lunc-
tion to cieate a custom ellect.
Solution
Use the animation lunction to togg|c Loth the height anu the opacity at the same time:
$(document).ready(function () {
$('#animate').click(function () {
$('.box').animate({ opacity: 'toggle', height: 'toggle' });
return false;
});
});
7.4 Simultaneously Sliding and Fading Elements | 161
Discussion
Using the animate methou allows us to specily exactly which CSS piopeities we want
to animate loi the ellect.
Ve aie also using toggle as the enu point value. This way, the animate methou takes
the cuiient height in the initial state anu toggles it to eithei zeio oi 100 peicent ol the
initial state.
In oui example, the initial state ol the Lox is visiLle. Il we want it to sliue anu laue
into view, then we only neeu to set the uisplay piopeity to none in the stylesheet.
Vaining: theie is no neeu to set the height to zeio in the style; in lact, uoing so will
mean the animate won`t expanu to the coiiect height Lecause it will toggle Lack anu
loith Letween zeio height (liom the CSS) anu zeio height anu uisplay none (the linal
point ol slideUp).
7.5 Applying Sequential Effects
Problem
You want an ellect to occui on one set ol elements altei anothei ellect occuis on a
uilleient set ol elements. This is simple to solve il you just have one othei ellect to
execute, Lut il you want to apply the ellect one-Ly-one to any numLei ol elements, the
coue cou|d Lecome uillicult to maintain.
Solution
This solution uses the stanuaiu template outlineu at the Leginning ol this chaptei,
except that we have multiple copies ol the div.box element on the page. This solution
is uesigneu as such that we can Le uealing with any numLei ol div.box elements, liom
just one single element to many, Lecause the automatic seguence solution can hanule
them all.
Manual callback
The Lasic appioach to applying seguential ellects woulu Le to use the callLack. This
woulu also Le useu il the next ellect is uilleient liom the liist:
$(document).ready(function () {
var $boxes = $('.box').hide();
$('#animate').click(function () {
$boxes.eq(0).fadeIn('slow', function () {
$boxes.eq(1).slideDown('slow');
});
});
});
162 | Chapter 7:Effects
Automatic sequence
This alteinative methou, Laseu on Dave Methvin`s solution, will iepeat in seguence the
ellect on any numLei ol elements:
$(document).ready(function () {
var $boxes = $('.box').hide(),
div = 0;
$('#animate').click(function () {
$($boxes[div++] || []).fadeIn('slow', arguments.callee);
});
});
Discussion
The simple solution uses the callLack leatuie to then step in to the next animation in
the seguence. The selectoi we use taigets the liist div.box; howevei, this uoesn`t scale
Lecause it is expecting theie to Le two anu only two animateu elements. Any less anu
the coue Lieaks. Any moie, anu some elements will Le misseu.
Il we have many moie, oi even an unknown numLei ol elements we neeu to animate
in seguence, then Dave Methvin`s solution is peilect.
Theie aie two tiicks to the coue. The liist is the lailovei to an empty aiiay:
$($boxes[div++] || [])
This coue inciements the inuex countei, anu il the element uoesn`t exist, it passes an
empty aiiay to jQueiy.
Vhen the jQueiy iesult set is empty, iunning an animation uoesn`t uo anything. Since
the iesult is empty, jQueiy docsn`t pass any DOM elements to the chaineu call, anu
theieloie any callLacks given to the chaineu methou won`t Le calleu eithei.
Foi example, il we ian the lollowing coue, the aleit Lox woulu nevei appeaiwhich
is a key ingieuient to making this iecipe woik:
$('made-up-element').show(function () {
alert('will never appear');
});
The seconu tiick to this iecipe is the callLack aigument:
arguments.callee
arguments is a keywoiu in ]avaSciipt ieleiiing to a local vaiiaLle that all lunctions have
access to. The arguments oLject is similai to any aiiay Lut uoes not have any ol the aiiay
methous (such as slice) oi piopeities except length.
7.5 Applying Sequential Effects | 163
arguments also contains a ieleience to the cuiiently executing lunction in the
arguments.callee piopeity. This is uselul loi iecuisive lunction calls, which is exactly
how we aie using the piopeity in this solution.
This solution says to keep inciementing thiough the $boxes jQueiy collection anu, on
completion ol the animation, iecuisively execute the lunction. This continues until the
<div> inuex goes Leyonu the length ol the $boxes jQueiy collection ($boxes.length), at
which point an empty aiiay is useu as the jQueiy collection, anu thus the callLack is
not executeu, causing the coue to linish iunning.
7.6 Determining Whether Elements Are Currently Being
Animated
Problem
Vhen an animation is in piogiess, we may want to pievent the usei liom tiiggeiing the
animation to iun again until the initial animation has linisheu.
An example ol this may Le il the usei clicks a Lutton to tiiggei some animation. This
coulu Le to ieveal some piece ol inloimation. Foi oui paiticulai contiiveu example,
when the usei clicks the Lutton, we will shake the Lox Lack anu loith.
Il the usei keeps clicking the Lutton, we won`t want to keep gueuing animations, so
we neeu to test whethei the animation is alieauy iunning anu, il it is, ignoie the ieguest
to animate.
Solution
Foi this solution, I want to incluue some ueLugging inloimation, so I`ve incluueu a
<div> element with the ID ol debug, anu we`ll appenu log messages to this to help us
see what`s happening.
Ve will use the :animated custom jQueiy selectoi to test whethei the animation is
iunning:
$(document).ready(function () {
var speed = 100;
$('#animate').click(function () {
$('.box')
.filter(':not(:animated)')
.animate({ marginLeft: 10 }, speed, function () {
$('#debug').append('<p>Starting animation.<p>');
})
.animate({ marginLeft: 10 }, speed)
.animate({ marginLeft: 10}, speed)
.animate({ marginLeft: 10 }, speed)
.animate({ marginLeft: 10}, speed)
.animate({ marginLeft: 10 }, speed)
164 | Chapter 7:Effects
.animate({ marginLeft: 0}, speed, function () {
$('#debug').append('<p>Finished animation.</p>');
}); // end of our long chain
});
});
Discussion
In this contiiveu example, we use multiple calls to the animate methou to make the Lox
shake Lack anu loith (though il this weie ieguiieu in ieality, it might Le Lettei to use
a Louncing easing insteau!).
This animation is tiiggeieu when the usei clicks the animate Lutton.
I have incluueu two callLack lunctions to show when the animation staits anu linishes.
Note that even though theie aie seveial lines, Lecause ol the way chaining woiks, this
is in lact one single line ol ]avaSciipt staiting liom $('.box') anu enuing on }); // end
of our long chain.
The lollowing line ol jQueiy lilteis out any div.box element that is cuiiently Leing
animateu liom oui collection anu only iunning the suLseguent animations on the ie-
maining elements:
.filter(':not(:animated)')
Since we have a single div.box element in oui example, the animation will iun only il
the element isn`t animating alieauy.
7.7 Stopping and Resetting Animations
Problem
Il an animation is iunning, we may Le ieguiieu to stop it in miullow. A common pioL-
lem is seen when using a mouseovei anu a mouseout to tiiggei an animation to show
anu hiue a paiticulai Llock ol content.
Il the mouse is iun in anu out ol the tiiggei aiea, the animation continuously tiiggeis;
loi example, the content Llock woulu keep sliuing up anu uown until it completeu the
numLei ol times it was tiiggeieu.
One appioach coulu Le to use the :animated selectoi to liltei out the element loi ani-
mation. Howevei, you may want to laue an element Lack out ol view when the usei
moves the mouse away liom the tiiggei iathei than letting it complete. This can Le
solveu with the stop() methou.
7.7 Stopping and Resetting Animations | 165
Solution
Ve have auueu a CSS style to the div.box element to set the opacity to zeio.
Insteau ol having the usei c|ic| the Lutton to tiiggei the ellect, we`ie iunning the ani-
mation when the mouse hovcrs ovei the Lutton. This is just to show that without the
stop() calls, the animation woulu iun out ol contiol:
$(document).ready(function () {
$('#animate').hover(function () {
$('.box').stop().fadeTo(200, 1);
}, function () {
$('.box').stop().fadeTo(200, 0);
});
});
Discussion
Typically this pioLlem woulu Le solveu using a comLination ol fadeIn() anu
fadeOut(). Howevei, il this weie useu, liistly without stop(), then the ellect keeps
iepeating each time the mouse hoveis ovei the Lutton.
To pievent this, we inseit the stop() commanu Leloie gueuing on the next animation.
The Lig auvantage ol this is that it stops the animation miullow. This means il the
opacity ol the element is at 0.5 (oi 50 in IE), it will pioceeu with the next animation
with the staiting point ol 0.5.
Since we aie now stopping in the miuule ol the opacity animation, it also means we
can`t piopeily use fadeIn() anu fadeOut(). Ve have to explicitly state wheie we want
to laue to. So, now we aie using fadeTo(), passing in the uuiation anu then the taiget
opacity.
Now when the usei moves theii mouse Lack anu loith ovei the Lutton, the animation
uoesn`t iepeat Lut laues in anu out in a single smooth tiansition.
7.8 Using Custom Easing Methods for Effects
Problem
jQueiy comes with only two Luilt-in easing lunctions: swing anu linear. The uelault is
swing. Il we want to make oui animations a little moie inteiesting, then we might want
to use a uilleient easing lunctionthis coulu give us a Lounce animation, oi elastic, oi
peihaps just an animation that slows uown as it`s coming to its enu.
Ve can manually auu easing lunctions, Lut we can also incluue a pieuelineu collection
using the jquery.easing plugin, which can Le uownloaueu liom http://jqucry-coo|boo|
.con/go/casing/.
166 | Chapter 7:Effects
Solution
By liist incluuing jquery.easing.1.3.js altei we incluue the jQueiy liLiaiy, we can now
make use ol any one ol the 31 new easing lunctions:
$(document).ready(function () {
$('#animate').click(function () {
$('.box').animate({ scrollTop: '+=100' },
{ duration: 400, easing: 'easeOutElastic' });
});
});
Discussion
By incluuing the easing liLiaiy, we can specily a laige iange ol values in the easing
piopeity in the options paiametei. The animate methou also suppoits passing easing
as the thiiu paiametei, so the pieceuing solution coulu Le wiitten as lollows:
$('.box').animate({ scrollTop: '+=100' }, 400, 'easeOutElastic');
To cieate youi own custom easing lunction, you can extenu the easing oLject using this:
jQuery.extend(jQuery.easing, {
customEasing: function(x, t, b, c, d) {
return c*(t/=d)*t + b;
},
});
The pieceuing example is the eguation loi the easeInQuad easing. All easing lunctions
take live paiameteis:
fraction
The cuiient position ol the animation, as measuieu in time Letween 0 (the Legin-
ning ol the animation) anu 1 (the enu ol the animation)
elapsed
The numLei ol milliseconus that have passeu since the Leginning ol the animation
(seluom useu)
attrStart
The Leginning value ol the CSS attiiLute that is Leing animateu
attrDelta
The uilleience Letween the stait anu enu values ol the CSS attiiLute that is Leing
animateu
duration
The total numLei ol milliseconus that will pass uuiing the animation (seluom useu)
7.8 Using Custom Easing Methods for Effects | 167
7.9 Disabling All Effects
Problem
Youi usei oi weL application may ieguiie that all animations aie uisaLleu, Lut the ellect
ol ievealing inloimation oi sciolling (oi whichevei animation type) may still Le
ieguiieu.
This may Le a peisonal pieleience, the usei may Le using a low-iesolution uevice, oi it
may Le Lecause the usei linus the animations pioLlematic in theii Liowsing.
jQueiy has a way to uisaLle all animations liom one access point Lut still suppoits the
animate methou anu its linal value.
Solution
$.fx.off = true;
$(document).ready(function () {
$('#animate').click(function () {
$('.box').animate({ width: '+=100', height: '+=100' });
});
});
Discussion
By setting fx to off using the lollowing line, all animation calls have the same ellect as
calling css() uiiectly:
$.fx.off = true;
This can Le set at any point anu it will uisaLle the animations, which means it can Le
olleieu as a usei pieleience. To enaLle animations again, you simply set the llag to
false:
$.fx.off = false;
7.10 Using jQuery UI for Advanced Effects
Problem
Il you want to cieate moie complicateu ellects, it is ceitainly possiLle using the
animate methou. This might Le loi a weL application that neeus to animate a whole
iange ol CSS piopeities on an element, oi peihaps theie is a special way a uialog Lox
must uisappeai when closeusay, loi instance, exploue away on the scieen (see Fig-
uie 7-2).
168 | Chapter 7:Effects
Iigurc 7-2. Thc cxp|odc cjjcct running against thc div.box c|cncnt
Solution
Downloau the jQueiy UI liLiaiy liom http://jqucry-coo|boo|.con/go/jqucryui-down
|oad. The liLiaiy can now Le incluueu altei jQueiy is incluueu anu the new ellects
plugin is availaLle.
Foi this solution, I have auueu an extia Lutton to show two ellects anu auueu a new
class to oui CSS.
CSS
.big {
font-size: 400%;
width: 500px;
height: 500px;
line-height: 100%;
}
jQuery
$(document).ready(function () {
$('#animate').click(function () {
$('.box').toggleClass('big', 2000);
});
$('#effect').click(function () {
$('.box').effect('explode', null, 2000);
7.10 Using jQuery UI for Advanced Effects | 169
});
});
Discussion
The jQueiy UI ellects liLiaiy also mouilies the way addClass, removeClass, anu toggle
Class woik; in paiticulai, you can supply a uuiation as the seconu paiametei, anu it
will animate a tiansition liom the cuiient state to the new class, woiking thiough all
new class piopeities.
So, the liist example auus the class big anu sets the animation to iun loi two seconus.
All the CSS piopeities liom the big class aie animateu onto the div.box element. Be-
cause the toggleClass methou has also Leen mouilieu Ly jQueiy UI, we aie aLle to
toggle Lack anu loith to the oiiginal state.
Seconu, we aie using the effect() methou, which is Lespoke to the jQueiy UI liLiaiy.
This methou olleis a collection ol show anu hiue lunctions.
The effect() methou ieguiies the option oLject passeu in as the seconu
vaiiaLle; this can Le null oi it can Le an empty oLject, Lut it must Le
pioviueu to Le aLle to pass in the uuiation.
Using the stiing explode, the div.box will split into nine pieces anu laue oll the page as
shown eailiei in Figuie 7-2.
At the time ol this wiiting, one oi two ellect types have slight siue ellects
in Salaii +. They uo woik in all othei A-giaue Liowseis as outlineu Ly
Yahoo! at http://dcvc|opcr.yahoo.con/yui/artic|cs/gbs/.
To see all the uilleient availaLle ellects, you can visit http://jqucry-coo|boo|.con/go/
jqucryui-cjjccts anu play with all the inteiactive uemos.
170 | Chapter 7:Effects
CHAPTER 8
Events
Aricl Flcslcr
8.0 Introduction
Events aie the main methou ol communication Letween a usei anu a weLsite oi weL
application. Most ol oui ]avaSciipt/jQueiy couing will Le iun in iesponse to a vaiiety
ol usei anu Liowsei events.
By uscr cvcnts, I mean Lasically keyLoaiu anu mouse inteiaction like click, mousedown,
keypress, etc. Browscr cvcnts aie mainly DOM events like document.ready,
window.onload, anu many othei events ielateu to DOM elements.
Vhen couing Ajax applications, we also have custom jQueiy Ajax cvcnts that aie uis-
patcheu uuiing the piocess ol an Ajax ieguest, that is, ajaxSend, ajaxComplete,
ajaxError, anu some moie.
jQueiy`s API is veiy consistent, especially when it comes to events. Attaching a hanulei
to any kinu ol event is uone using the same coue stiuctuie:
jQuery( listener).bind( 'eventName', handlerFunction);
This syntax also applies to a louith categoiy that I haven`t mentioneu yet. jQueiy`s
event system can Le useu loi cvcnt-drivcn progranning
'
in which you can cieate youi
own custon cvcnts that can Le Lounu anu tiiggeieu as iegulai ones.
jQueiy also pioviues a shoitcut methou loi most common Liowsei anu Ajax events. A
mouel call using a shoitcut woulu look like this:
jQuery( listener).eventName( handlerFunction);
Vhen using bind(), eventName will Le a stiing wiappeu in eithei single oi uouLle
guotes. Vhen using the shoitcut, you simply put the event`s name as the jQueiy
methou`s name.
' http://cn.wi|ipcdia.org/wi|i/Evcnt-drivcn_progranning
171
Heie`s an example ol Linuing a click hanulei, with anu without the shoitcut:
// Using bind()
jQuery('div').bind('click',function(e){...});
// Using the shortcut
jQuery('div').click(function(e){...});
Duiing this chaptei, I`ll use the shoitcuts when availaLle, just Lecause they`ie shoitei
anu easiei to ieau, in my opinion. Both woik egually, anu theie`s no auvantage to using
the shoitcut othei than claiity anu Lievity; it`s simply a mattei ol taste.
I`ll assume that you alieauy ieau Chaptei 1, wheie the document.ready event is explaineu
in uetail (Recipe 1.2). Il you have any uouLt aLout its use, uo consult that iecipe.
I also want to claiily that when I use the teim p|ugin, loi most cases I mean plugins,
wiugets, oi simply Llocks ol coue. Most jQueiy useis tenu to oiganize theii coue into
plugin-like stiuctuies, usually auuing names to jQueiy`s namespace.
Finally, jQueiy`s event mouule was highly mouilieu in 1.3. I will always mention when
something neeus to Le uone uilleiently, accoiuing to what jQueiy veision woulu
Le useu.
8.1 Attaching a Handler to Many Events
Problem
In many common situations, one neeus to Linu the same hanulei lunction to moie than
one event (on the same element, that is). You coulu always uo something like this:
jQuery('div').click(function(e){
alert('event');
})
.keydown(function(e){
alert('event');
});
That is not such a pioLlem il the lunction is shoit, Lut loi longei Llocks ol coue, ie-
peating them ovei anu ovei won`t Le that tiivial anu is uelinitely not the Lest appioach.
Solution
Theie`s moie than a single solution to this simple Lut iecuiient pioLlem.
One way to solve it without iepeating youisell too much woulu Le as lollows:
function handler(e){
alert('event');
}
jQuery('div').click(handler)
.keydown(handler);
172 | Chapter 8:Events
Delining a lunction once anu then ieleiiing to it multiple times is not a Lau appioach,
Lut theie`s an even simplei one pioviueu Ly jQueiy.
bind() accepts a list ol events sepaiateu Ly spaces. That means you can solve the pie-
vious pioLlem like this:
jQuery('div').bind'click keydown', function(e){
alert('event');
});
Discussion
You can also apply this Lehavioi to unbind() anu one().
To unLinu a ceitain lunction, you neeu to have a ieleience to it, so even il you aie using
the multievent leatuie, you still neeu to keep a ieleience to the hanulei. Il you uon`t
pass the lunction to unbind(), then any othei event hanulei Lounu to that event will Le
iemoveu as well:
function handler(e){
alert('event');
}
jQuery('div').bind('click keydown', handler);
// ...
jQuery('div').unbind('click keydown', handler);
8.2 Reusing a Handler Function with Different Data
Problem
You`ve come into a situation wheie you have many Linuings, anu the hanulei lunctions
look pietty similai. It uoesn`t mattei whethei these Linuings aie applieu to uilleient
element/event comLinations. The thing is, you uon`t want to iepeat youisell ovei anu
ovei (who uoes?).
Heie`s an example:
jQuery('#button1').click(function(e){
jQuery('div.panel').hide();
jQuery('#panel1').show();
jQuery('#desc').text('You clicked the red button');
});
jQuery('#button2').click(function(e){
jQuery('div.panel').hide();
jQuery('#panel2').show();
jQuery('#desc').text('You clicked the blue button');
});
8.2 Reusing a Handler Function with Different Data | 173
jQuery('#button3').click(function(e){
jQuery('div.panel').hide();
jQuery('#panel3').show();
jQuery('#desc').text('You clicked the green button');
});
As you can see, the only uilleiences noticeu on each hanulei aie the coloi anu the panel
to show. The amount ol coue woulu giow as you auu moie Luttons oi each time the
hanulei lunctions get laigei.
Solution
bind() accepts an optional data aigument to Le Lounu togethei with each specilic han-
ulei lunction. The uata values will Le accessiLle liom within this lunction Ly accessing
event.data
That way, you uon`t neeu to woiiy aLout waiting loi the element to Le ieauy
in oiuei to Linu the events.
To ieau moie aLout event uelegation, check Recipe S.10.
Any other situation
Youi pioLlem isn`t aLout styling oi aLout events. Then you, my liienu, lall into the
woist gioup.
But uon`t panic! Theie`s a Lettei solution than polling il you`ie conceineu aLout pei-
loimance. I`ll explain it at last.
Polling can Le implementeu with a simple inteival (setInterval) that checks
loi an element, anu once lounu, a ceitain lunction is iun, anu the inteival neeus to Le
cleaieu.
Theie aie two plugins that can aiu you with this. One is LiveQuery,
Il you want to consult the event oLject, to know whethei this methou has Leen calleu,
you can uo so Ly calling event.isImmediatePropagationStopped(),
http://p|ugins.jqucry.con/projcct/nouscwhcc|
9.3 Creating Your Own Events | 197
drag, drop
Diag anu uiop suppoit maskeu as simple events.
focusin, focusout
This snippet (not an actual plugin) oiiginally wiitten Ly ]oin Zaelleiei was latei
auueu via plugins to achieve event uelegation ol focus anu blur events.
Checking these plugins can Le a goou stait il you`ie planning on auuing new events to
jQueiy.
9.4 Letting Event Handlers Provide Needed Data
Problem
You neeu to allow othei plugins (oi just simple jQueiy coue) to chime in anu mouily
ceitain vaiiaLles Leloie you peiloim the ieguesteu action.
Solution
Use events to notily othei sciipts aLout the action that is aLout to Le caiiieu out.
It is possiLle to get uata that is gatheieu liom the actioneu event hanuleis.
Il none is pioviueu, you coulu then use some uelault option ol youi choice.
You`ll see how to uo this accoiuing to what jQueiy veision you aie using.
Discussion
How can we do this with jQuery 1.3+?
Since jQueiy 1.3, with the auuition ol jQuery.Event, this can Le achieveu in a nicei way.
The olu way still woiks loi triggerHandler() Lut not loi jQuery.trigger().
Foi the coue we`ll see now, we will neeu to cieate a jQuery.Event:
var e = jQuery.Event('updateName');
Now, to call the hanuleis anu ietiieve the value, we`ll pass the event oLject to
trigger() anu then letch the uata liom the event oLject:
jQuery('#element').trigger(e);
alert( e.result ); // Charles
As I saiu at the Leginning, this uoesn`t woik nicely when many hanuleis aie Lounu anu
is, in geneial teims, a little unieliaLle anu liagile.
So, how can we communicate event hanuleis anu the lunction tiiggeiing the event?
http://p|ugins.jqucry.con/projcct/drag, http://p|ugins.jqucry.con/projcct/drop
198 | Chapter 9:Advanced Events
The answei is, thiough the event oLject that we`ie passing.
The jQuery.Event oLject passeu to trigger() will Le the same that is ieceiveu Ly each
hanulei as its liist aigument.
This means that we can uo this:
jQuery('#name').bind('updateName', function(e){
e.name = this.value;
});
var e = jQuery.Event('updateName');
jQuery('#name').trigger(e);
alert( e.name );
This example uoesn`t uillei much liom simply accessing e.result, Lut what aLout
multiple event hanuleis that opeiate on the same event oLject?
jQuery('#first').bind('update', function(e){
e.firstName = this.value;
});
jQuery('#last').bind('update', function(e){
e.lastName = this.value;
});
var e = jQuery.Event('update');
jQuery('#first, #last').trigger(e);
alert( e.firstName );
alert( e.lastName );
Ve now have a way ol allowing any numLei ol event hanuleis to pioviue neeueu in-
loimation loi a lunction to iun. Neeuless to say, you can call trigger() seveial times,
passing the same event oLject.
As saiu Leloie, it`u Le wise to pieset the event oLject with uelault values (il applicaLle).
Youi coue shoulun`t iely on the lact that otheis uiu suLsciiLe to a ceitain event.
Il no uelault value can Le useu, then you can always aLoit the call oi thiow an eiioi.
How this was achieved before jQuery 1.3
Oluei veisions ol jQueiy only alloweu the useis to get a single value, which woulu Le
ietuineu when calling jQuery.trigger() anu/oi triggerHandler().
It lookeu something like this:
jQuery('#element').bind('updateName', function(){
return 'Charles';
});
var name = jQuery('#element').triggerHandler('updateName');
alert( name ); // Charles
This was OK until you hau moie than one event hanulei ietuining uata. At that point,
it was a mattei ol who comes last to ueciue which one`s uata woulu Le ietuineu.
9.4 Letting Event Handlers Provide Needed Data | 199
Allowing event handlers to prevent actions
This is ieally a specialization ol what we just saw. Event oLjects, Ly uesign, have a
methou calleu preventDefault(). This methou is useu on native events to aLoit com-
mon actions like clicks on links, Lut it has no ieal use on custom events.
Ve coulu take auvantage ol this anu use this methou to allow othei sciipts to pievent
actions that aie aLout to Le peiloimeu.
I`ll now show you an example ol an action. I`ll use the mini plugin intiouuceu on
Recipe 9.2, Lut that is ceitainly not a ieguiiement to use this:
var remote = jQuery.listener({
request:function( url, callback ){
jQuery.ajax({ url:url, success:callback });
}
});
// Do a request
remote.request('contact.html', function( html ){
alert( html );
});
Now suppose we want to allow an exteinal sciipt to aLoit ceitain ieguests when
neeueu. Ve neeu to mouily remote.request like this:
var remote = jQuery.listener({
request:function( url, callback ){
var e = jQuery.Event('beforeRequest');
e.url = url;
this.trigger(e);
if( !e.isDefaultPrevented() )
jQuery.ajax({ url:url, success:callback });
}
});
e.isDefaultPrevented() will ietuin whethei e.preventDefault() was evei calleu on this
oLject.
Any exteinal sciipt can now uo something like this:
remote.bind('beforeRequest', function(e){
if( e.url == 'contact.html' )
e.preventDefault();
});
Retuining lalse (within the lunction) woulu have neaily the same ellect as calling
e.preventDefault(). It will also stop the event piopagation, which coulu Le uesiiaLle.
Neeuless to say, in a situation like this, we coulu use what we leaineu Leloie to allow
the URL (oi post uata il auueu) to Le mouilieu Ly hanuleis.
200 | Chapter 9:Advanced Events
9.5 Creating Event-Driven Plugins
Problem
You want youi plugin to Le contiollaLle liom the outsiue. One shoulu Le aLle to tell
the plugin to uo something at any time. Theie coulu Le many instances (calls) ol a
plugin, Lut oui action shoulu only Le executeu in the context we pioviue.
Solution
One way to uo this is inueeu using events.
Vhen a plugin is calleu, it Linus lunctions on each matcheu element that once tiiggeieu,
anu it will peiloim the uesiieu actions.
As a possiLle siue solution, each time the plugin is calleu, insteau ol iespecting the
chaining, it coulu ietuin an oLject that contains the Linuings anu allows exteinal ma-
nipulation (use the plugin liom Recipe 9.2).
This allows you to call the plugin many times on the same element without messing up
the events.
Discussion
An example
Ve`ll now cieate a simple sliueshow plugin. I`ll Lase this plugin on an existing plugin
ol mine calleu jQuery.SerialScroll.