jQuery实战第三版


MANNING Bear Bibeault Yehuda Katz Aurelio De Rosa FOREWORDS BY Dave Methvin John Resig IN ACTION THIRD EDITION Praise for Earlier Editions of jQuery in Action Every technical book should be like this one…concise but clear, humorous but not silly, and one that answers all the questions it raises, quickly. The reader is never left wondering “But what about...” for more than a sentence or two. —JRoller Online Book Reviews Thanks to the authors and their exemplary style, this comprehensive book, or operating manual as it might be called, can be taken in a front-to-back approach to learn from scratch, or as a ref- erence for those already dabbling in jQuery and needing verification of best practices. —Matthew McCullough Denver Open Source Users Group With its capable technical coverage, extensive use of sample code, and approachable style, this book is a valuable resource for any web developer seeking to maximize the power of JavaScript, and a must-have for anyone interested in learning jQuery. —Michael J. Ross Web Developer and Slashdot Contributor An excellent work, a worthy successor to others in Manning’s In Action series. It is highly read- able and chock-full of working code. The Lab Pages are a marvelous way to explore the library, which should become an important part of every web developer’s arsenal. Five stars all ‘round! —David Sills JavaLobby, DZone I highly recommend the book for learning the fundamentals of jQuery and then serving as a good reference book as you leverage the power of jQuery more and more in your daily development. —David Hayden MVP C#, Codebetter.com I highly recommend this book to any novice or advanced JavaScript developers who want to get serious about JavaScript and start writing optimized and elegant code without all the hassle of traditional JavaScript code authoring. —Val’s Blog The Elements of Style for JavaScript. —Joshua Heyer Trane Inc. Licensed to Mark Watson Licensed to Mark Watson jQuery in Action THIRD EDITION BEAR BIBEAULT YEHUDA KATZ AURELIO DE ROSA MANNING Shelter Island Licensed to Mark Watson For online information and ordering of this and other Manning books, please visit www.manning.com. The publisher offers discounts on this book when ordered in quantity. For more information, please contact Special Sales Department Manning Publications Co. 20 Baldwin Road PO Box 761 Shelter Island, NY 11964 Email: orders@manning.com ©2015 by Manning Publications Co. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in the book, and Manning Publications was aware of a trademark claim, the designations have been printed in initial caps or all caps. Recognizing the importance of preserving what has been written, it is Manning’s policy to have the books we publish printed on acid-free paper, and we exert our best efforts to that end. Recognizing also our responsibility to conserve the resources of our planet, Manning books are printed on paper that is at least 15 percent recycled and processed without the use of elemental chlorine. Manning Publications Co. Development editors: Jeff Bleiel, Sean Dennis 20 Baldwin Road Technical development editor: Al Scherer PO Box 761 Copyeditor: Linda Recktenwald Shelter Island, NY 11964 Proofreader: Melody Dolab Technical proofreader: Richard Scott-Robinson Typesetter: Dottie Marsico Cover designer: Marija Tudor ISBN 9781617292071 Printed in the United States of America 12345678910–EBM–201918171615 Licensed to Mark Watson To Annarita, because you give balance to my life —Aurelio Licensed to Mark Watson Licensed to Mark Watson vii brief contents PART 1STARTING WITH JQUERY............................................... 1 1 ■ Introducing jQuery 3 PART 2CORE JQUERY.............................................................21 2 ■ Selecting elements 23 3 ■ Operating on a jQuery collection 52 4 ■ Working with properties, attributes, and data 79 5 ■ Bringing pages to life with jQuery 99 6 ■ Events are where it happens! 134 7 ■ Demo: DVD discs locator 172 8 ■ Energizing pages with animations and effects 188 9 ■ Beyond the DOM with jQuery utility functions 224 10 ■ Talk to the server with Ajax 260 11 ■ Demo: an Ajax-powered contact form 301 PART 3ADVANCED TOPICS ....................................................317 12 ■ When jQuery is not enough...plugins to the rescue! 319 13 ■ Avoiding the callback hell with Deferred 358 14 ■ Unit testing with QUnit 385 15 ■ How jQuery fits into large projects 412 Licensed to Mark Watson Licensed to Mark Watson ix contents foreword to the third edition xvii foreword to the first edition xix preface xxi acknowledgments xxiii about this book xxv about the authors xxix PART 1STARTING WITH JQUERY...................................... 1 1 Introducing jQuery 3 1.1 Write less, do more 4 1.2 Unobtrusive JavaScript 6 Separating behavior from structure 7 ■ Segregating the script 7 1.3 Installing jQuery 8 Choosing the right version 9 ■ Improving performances using a CDN 11 1.4 How jQuery is structured 13 Save space creating your own custom build 14 1.5 jQuery fundamentals 15 Properties, utilities, and methods 15 ■ The jQuery object 15 The document ready handler 17 ■ Summary 19 Licensed to Mark Watson CONTENTSx PART 2CORE JQUERY....................................................21 2 Selecting elements 23 2.1 Selecting elements for manipulation 24 2.2 Basic selectors 26 The All (or Universal) selector 27 ■ The ID selector 30 The Class selector 30 ■ The Element selector 31 2.3 Retrieving elements by their hierarchy 32 2.4 Selecting elements using attributes 34 2.5 Introducing filters 37 Position filters 38 ■ Child filters 39 ■ Form filters 42 Content filters 43 ■ Other filters 44 ■ How to create custom filters 46 2.6 Enhancing performances using context 49 2.7 Testing your skills with some exercises 50 Exercises 50 ■ Solutions 51 2.8 Summary 51 3 Operating on a jQuery collection 52 3.1 Generating new HTML 53 3.2 Managing the jQuery collection 55 Determining the size of a set 57 ■ Obtaining elements from a set 57 ■ Getting sets using relationships 62 Slicing and dicing a set 66 ■ Even more ways to use a set 75 3.3 Summary 77 4 Working with properties, attributes, and data 79 4.1 Defining element properties and attributes 80 4.2 Working with attributes 83 Fetching attribute values 83 ■ Setting attribute values 84 Removing attributes 86 ■ Fun with attributes 86 4.3 Manipulating element properties 88 4.4 Storing custom data on elements 91 4.5 Summary 98 Licensed to Mark Watson CONTENTS xi 5 Bringing pages to life with jQuery 99 5.1 Changing element styling 100 Adding and removing class names 100 ■ Getting and setting styles 104 5.2 Setting element content 114 Replacing HTML or text content 114 ■ Moving elements 116 Wrapping and unwrapping elements 122 ■ Removing elements 126 ■ Cloning elements 128 ■ Replacing elements 129 5.3 Dealing with form element values 131 5.4 Summary 133 6 Events are where it happens! 134 6.1 Understanding the browser event models 136 The DOM Level 0 Event Model 136 ■ The DOM Level 2 Event Model 143 ■ The Internet Explorer Model 148 6.2 The jQuery Event Model 149 Attaching event handlers with jQuery 149 ■ Removing event handlers 156 ■ Inspecting the Event instance 159 Triggering event handlers 160 ■ Shortcut methods 165 How to create custom events 168 ■ Namespacing events 169 6.3 Summary 170 7 Demo: DVD discs locator 172 7.1 Putting events (and more) to work 173 Filtering large data sets 174 ■ Element creation by template replication 176 ■ Setting up the mainline markup 178 Adding new filters 179 ■ Adding the controls templates 182 Removing unwanted filters and other tasks 183 ■ Showing the results 183 ■ There’s always room for improvement 186 7.2 Summary 187 8 Energizing pages with animations and effects 188 8.1 Showing and hiding elements 189 Implementing a collapsible “module” 190 ■ Toggling the display state of elements 192 Licensed to Mark Watson CONTENTSxii 8.2 Animating the display state of elements 193 Showing and hiding elements gradually 193 ■ Introducing the jQuery Effects Lab Page 198 ■ Fading elements into and out of existence 200 ■ Sliding elements up and down 202 ■ Stopping animations 203 8.3 Adding more easing functions to jQuery 204 8.4 Creating custom animations 206 A custom scale animation 209 ■ A custom drop animation 210 A custom puff animation 211 8.5 Animations and queuing 213 Simultaneous animations 213 ■ Queuing functions for execution 215 ■ Inserting functions into the effects queue 221 8.6 Summary 222 9 Beyond the DOM with jQuery utility functions 224 9.1 Using the jQuery properties 225 Disabling animations 226 ■ Changing the animations rate 226 ■ The $.support property 227 9.2 Using other libraries with jQuery 228 9.3 Manipulating JavaScript objects and collections 232 Trimming strings 232 ■ Iterating through properties and collections 233 ■ Filtering arrays 235 ■ Translating arrays 237 ■ More fun with JavaScript arrays 239 Extending objects 242 ■ Serializing parameter values 244 Testing objects 248 ■ Parsing functions 251 9.4 Miscellaneous utility functions 254 Doing nothing 254 ■ Testing for containment 254 Prebinding function contexts 255 ■ Evaluating expressions 257 ■ Throwing exceptions 258 9.5 Summary 259 10 Talk to the server with Ajax 260 10.1 Brushing up on Ajax 261 Creating an XHR instance 261 ■ Initiating the request 264 Keeping track of progress 265 ■ Getting the response 265 10.2 Loading content into elements 266 Loading content with jQuery 267 ■ Loading dynamic HTML fragments 271 Licensed to Mark Watson CONTENTS xiii 10.3 Making GET and POST requests 276 Getting data with GET 278 ■ Getting JSON data 280 Dynamically loading script 281 ■ Making POST requests 283 ■ Implementing cascading dropdowns 284 10.4 Taking full control of an Ajax request 289 Making Ajax requests with all the trimmings 289 ■ Setting request defaults 294 ■ Handling Ajax events 295 ■ Advanced Ajax utility functions 298 10.5 Summary 300 11 Demo: an Ajax-powered contact form 301 11.1 The features of the project 302 11.2 Creating the markup 304 11.3 Implementing the PHP backend 305 11.4 Field validation using Ajax 307 11.5 Even more fun with Ajax 309 Hiding the dialog box 311 11.6 Improving the user experience using effects 311 Toggling the effects 312 11.7 A note on accessibility 313 11.8 Summary 314 PART 3ADVANCED TOPICS ...........................................317 12 When jQuery is not enough...plugins to the rescue! 319 12.1 Why extend jQuery? 320 12.2 Where to find plugins 320 How to use a (well-written) plugin 321 ■ Great plugins for your projects 324 12.3 The jQuery plugin authoring guidelines 325 File- and function-naming conventions 325 ■ Beware the $ 326 ■ Taming complex parameter lists 327 Keep one namespace 330 ■ Namespacing events and data 333 ■ Maintaining chainability 337 Provide public access to default settings 337 12.4 Demo: creating a slideshow as a jQuery plugin 340 Setting up the markup 343 ■ Developing Jqia Photomatic 344 Licensed to Mark Watson CONTENTSxiv 12.5 Writing custom utility functions 351 Writing a date formatter 352 12.6 Summary 356 13 Avoiding the callback hell with Deferred 358 13.1 Introduction to promises 359 13.2 The Deferred and Promise objects 362 13.3 The Deferred methods 363 Resolving or rejecting a Deferred 364 ■ Execute functions upon resolution or rejection 365 ■ The when() method 369 Notifying about the progress of a Deferred 371 ■ Follow the progress 372 ■ Using the Promise object 374 ■ Take it short with then() 377 ■ Always execute a handler 381 ■ Determine the state of a Deferred 381 13.4 Promisifying all the things 382 13.5 Summary 384 14 Unit testing with QUnit 385 14.1 Why is testing important? 386 Why unit testing? 387 ■ Frameworks for unit testing JavaScript 388 14.2 Getting started with QUnit 389 14.3 Creating tests for synchronous code 392 14.4 Testing your code using assertions 394 equal(), strictEqual(), notEqual(), and notStrictEqual() 394 The other assertion methods 397 ■ The throws() assertion method 399 14.5 How to test asynchronous tasks 400 14.6 noglobals and notrycatch 403 14.7 Group your tests in modules 404 14.8 Configuring QUnit 405 14.9 An example test suite 407 14.10 Summary 411 15 How jQuery fits into large projects 412 15.1 Improving the performance of your selectors 413 Avoiding the Universal selector 414 ■ Improving the Class Licensed to Mark Watson CONTENTS xv selector 414 ■ Don’t abuse the context parameter 415 Optimizing filters 416 ■ Don’t overspecify selectors 417 15.2 Organizing your code into modules 418 The object literals pattern 419 ■ The Module pattern 420 15.3 Loading modules with RequireJS 421 Getting started with RequireJS 422 ■ Using RequireJS with jQuery 424 15.4 Managing dependencies with Bower 425 Getting started with Bower 426 ■ Searching a package 427 Installing, updating, and deleting packages 428 15.5 Creating single-page applications with Backbone.js 429 Why use an MV* framework? 430 ■ Starting with Backbone.js 432 ■ Creating a Todos manager application using Backbone.js 435 15.6 Summary 445 15.7 The end 446 appendix JavaScript that you need to know but might not! 447 index 465 Licensed to Mark Watson Licensed to Mark Watson xvii foreword to the third edition A decade ago, John Resig imagined a JavaScript library that would simplify the way people built web sites. Today, that library, jQuery, is used by more than 80% of all web sites that use JavaScript, according to BuiltWith.com. It would be hard to call yourself a web developer today without knowing jQuery. On the technical side, jQuery simplifies the long-winded native method calls that browsers use and shrinks the number of lines of code that it takes to get things done. That’s why jQuery’s motto is “Write less, do more.” jQuery also paves over the differ- ences in behavior—and even some outright bugs—that exist in browsers. That simpli- fies both development and testing. From the start, jQuery was designed so that it could be extended by others. The jQuery plugin model lets anyone build specialized functionality on top of what jQuery already offers. There are thousands of jQuery plugins that do everything from light- boxes to form validation. The result is that many people with only a modest amount of programming skill are able to create beautiful and functional web sites by building on the work that others have done. Still, code alone is not what made jQuery popular. From the beginning, a strong community of helpful developers filled online forums and mailing lists to answer ques- tions for newcomers. The insight gained from those discussions led to better docu- mentation, training classes, and books like this one. This book is a great way to learn jQuery. Early on, it covers a central tenet of jQuery’s API, which is to select some elements on a web page and do something with them. That same pattern applies whether you are hiding, showing, animating, remov- ing, or changing an element’s appearance. The selection process uses the standard CSS selector syntax, with some jQuery enhancements that give selection even more power. Licensed to Mark Watson FOREWORD TO THE THIRD EDITIONxviii I must confess that the chapter on events is my favorite because my first major code contribution to jQuery was the rewrite of the event module in jQuery 1.7. This chap- ter does a great job of explaining the purpose and usefulness of events on a web page, which are the main way that you can be notified of how the user is interacting with the web page. Nearly every jQuery operation you do is started through an event of some kind. I’m also glad this book covers some topics often ignored, such as unit testing and organization of large projects. Many small projects eventually turn into large ones, and the advice in these chapters can help you to manage that growth in a way that reduces maintenance headaches. The chapters building demo applications do a great job of showing how all the parts of jQuery fit together and demonstrate important concepts like templating that are central to all modern JavaScript frameworks and applications. Even today, I feel a bit amazed by demos like this showing it’s possible to build something useful with very little code. Aurelio De Rosa has been a contributor to the jQuery community for several years and is a member of jQuery’s content team that ensures jQuery’s online documenta- tion is up-to-date. His work on this latest edition of jQuery in Action gives you timely information that reflects the most recent version of the library. Aurelio has also made jQuery’s online documentation better in the process of writing this book by uncover- ing inconsistencies and missing information. You, as a reader of this book and soon-to- be jQuery developer, are the lucky beneficiary. Go forward and, “Write less, do more!” DAVE METHVIN PRESIDENT, JQUERY FOUNDATION Licensed to Mark Watson xix foreword to the first edition It’s all about simplicity. Why should web developers be forced to write long, complex, book-length pieces of code when they want to create simple pieces of interaction? There’s nothing that says that complexity has to be a requirement for developing web applications. When I first set out to create jQuery, I decided that I wanted an emphasis on small, simple code that served all the practical applications that web developers deal with day to day. I was greatly pleased as I read through jQuery in Action to see in it an excellent manifestation of the principles of the jQuery library. With an overwhelming emphasis on practical, real-world code presented in a terse, to-the-point format, jQuery in Action will serve as an ideal resource for those looking to familiarize themselves with the library. What’s pleased me the most about this book is the significant attention to detail that Bear and Yehuda have paid to the inner workings of the library. They were thor- ough in their investigation and dissemination of the jQuery API. It felt like nary a day went by when I wasn’t graced with an email or instant message from them asking for clarification, reporting newly discovered bugs, or recommending improvements to the library. You can be safe knowing that the resource that you have before you is one of the best thought-out and researched pieces of literature on the jQuery library. One thing that surprised me about the contents of this book is the explicit inclu- sion of jQuery plugins and the tactics and theory behind jQuery plugin development. The reason why jQuery is able to stay so simple is through the use of its plugin architecture. It provides a number of documented extension points upon which plug- ins can add functionality. Often that functionality, while useful, is not generic enough Licensed to Mark Watson FOREWORD TO THE FIRST EDITIONxx for inclusion in jQuery itself—which is what makes the plugin architecture necessary. A few of the plugins discussed in this book, like the Forms, Dimension, and Live- Query plugins, have seen widespread adoption and the reason is obvious: they’re expertly constructed, documented, and maintained. Be sure to pay special attention to how plugins are utilized and constructed as their use is fundamental to the jQuery experience. With resources like this book, the jQuery project is sure to continue to grow and succeed. I hope the book will end up serving you well as you begin your exploration and use of jQuery. JOHN RESIG CREATOR OF JQUERY Licensed to Mark Watson xxi preface It always astonishes me when I think about the amount of work and effort I put into this book. When the people at Manning approached me to write the third edition of jQuery in Action, I knew that it wasn’t going to be a walk in the park, but I definitely underestimated the task. I thought, “This is going to be a piece of cake. A few months of work and I’ll be done.” Two years and many nights of work later, I don’t regret my choice. Writing this book has been an incredible journey, one that has let me improve my skills in many different ways. I’ve become a better developer and a better writer, and I’ve improved my jQuery skills. Two years ago, I was a web developer with a strong passion for jQuery, and I was grateful that this library solved so many problems for me for free. Before I started this project, my knowledge of jQuery was good, but without a doubt, writing and revising the chapters that you’re about to read forced me to dive much deeper and, as a result, I was able to take my skills to the next level. I also had the opportunity to discover new issues regarding the library and its documentation. Revising this book allowed me to contribute to jQuery on a regular basis—so much that I’ve been invited to join the jQuery team. Needless to say, this has been an unexpected and very welcome achieve- ment, and I’m proud to be part of such an amazing project. Now that you know how I came to embark on this journey, let’s tackle a crucial question: was this third edition really needed? I think it was, and this can be summed up with two basic facts. The previous edition of the book covers jQuery up to version 1.4, while the last version is 1.11, with jQuery 3 (also covered in this book) just around the corner. The second reason is that jQuery is definitely the most used JavaScript library out there. It’s employed by 63% of the top one million sites in the world, and Licensed to Mark Watson PREFACExxii by 17% of the internet. These two facts should lead you to understand that much has changed since the second edition of jQuery in Action was published, and that jQuery is not only still relevant, but isn’t going to disappear any time soon. In this third edition of the book, you’ll see quite a few changes. First of all, I deleted the chapters about the jQuery UI because both jQuery and the jQuery UI have grown so much that they deserve a book of their own. In addition, as you’ll see by turning the pages of this edition, I decided to add some advanced topics that weren’t covered in the previous edition. Finally, I’ve introduced many new examples, lab pages, snippets of code, live demos, and much more to make this edition even better. Turn this page, delve into the book, and start learning about the most-used JavaScript library in the world. Have fun! AURELIO DE ROSA Licensed to Mark Watson xxiii acknowledgments As with the previous editions of this book, and presumably with every successful book published, the number of people involved in getting the job done is impressive. It not only takes a lot of time to write a (good) book, but it also takes the contributions of many people with a variety of skills and roles in order to produce and publish it. The staff at Manning worked tirelessly to make sure that this book attained the level of quality expected, and I thank them for their efforts. Without them, this book would not have been possible. The “end credits” for this book include not only the publisher, Marjan Bace, but also the following people: Al Scherer, Ana Romac, Candace Gillhoolley, Cynthia Kane, Dottie Marsico, Jeff Bleiel, Kevin Sullivan, Linda Recktenwald, Mary Piergies, Melody Dolab, Ozren Harlovic, Robin de Jongh, Scott Meyers, and Sean Dennis. I thank them all, as well as the many others who worked behind the scenes. Another big thank you goes to the peer reviewers who helped in spotting errors, from simple typos to errors in terminology and code. The number of people who reviewed this book will probably surprise you, but they have been really helpful. For their contributions and insights, I’d like to thank Chris Maki, Christopher Haupt, Chuck Durfee, Francesco Bianchi, Gary A. Stafford, Gregor Zurowski, Jan Goyvaerts, Jean-François Morin, John D. Lewis, John Stemper, Karen Christenson, Keith Webster, Matt Forsythe, Ricardo Mano, Ryan Meeks, Suraj Kumar, William E. Wheeler, and Wil- lie Roberts. Special thanks to Richard Scott-Robinson, who worked as the book’s technical proofreader. He took the time and effort (and I’m sure this wasn’t fast or easy) to check each and every code example in the book in multiple environments. He also Licensed to Mark Watson ACKNOWLEDGMENTSxxiv offered invaluable contributions to the technical accuracy of the text and insightful comments, most of which are included in the volume you’re holding in your hands (or the digital copy you’re reading). Sincere thanks to Dave Methvin for penning the foreword to this edition and endorsing my work, and to Bear Bibeault and Yehuda Katz for writing the two best-sell- ing editions that preceded this one. On a personal level, the most important person I’d like to thank is my soon-to-be- wife Annarita. Your love, patience, and sweetness have been crucial throughout this journey and not only this one. You complained not once during the two years I spent working on this project instead of doing something with you. Your support and under- standing have been stunning and that’s why I’m dedicating this book to you. You, my dear Annarita, give balance to my life. Thank you for all the lovely moments spent together and those yet to come. I love you. Big thanks also go to my family: Raffaele, Eufemia, Giusy, Viola, my grandmothers Giuseppina and Anna, and my grandfather Aurelio. Thank you for all your love. You’re partly responsible for who I am and what I’ve done. You have supported me as much as you could, and I owe you a lot. I also want to thank Francesco Palladino. You’re the best friend a person could have. You have always been there for me when I needed it. I wish you all the best life has to offer and may all your dreams come true. And while I’m speaking about dreams, I also want to dedicate this book to all the people who have a burning passion and believe in their dreams. Don’t stop believing in them because others tell you to, even if it’s tough to keep going. One day, you’ll achieve them. To all the dreamers out there, I wish you good luck. I want to thank all the people who have contributed to form me and to shape the person that I have become, in one way or another: Albert Einstein, Ludwig van Beethoven, Lucius Annaeus Seneca, Roberto De Rosa, Leonardo Grisolia, and the anonymous umbrella seller. Finally, I want to thank all the people on the jQuery team. If I’ve written a good book, it’s because of the marvelous work you’ve been doing all these years. You rock! AURELIO DE ROSA Licensed to Mark Watson xxv about this book This book is for web developers who want to delve into jQuery, the most popular and adopted JavaScript library on the internet. The goal is to guide you, the reader, through the path of becoming a pro of jQuery regardless of your starting level, begin- ner or advanced. This tome covers the whole library in depth, including some addi- tional tools and frameworks such as Bower and QUnit, without forgetting to advocate best practices. Each API method is presented in an easy-to-digest syntax block that describes the parameters and the return value of the method. jQuery in Action, Third Edition covers topics from the simple, such as what’s jQuery and how to include it in a web page, to the advanced, such as the way the library implements Promises and how to create jQuery plugins. To help you in this journey, the content features many examples, three plugins, and three sample projects. It also includes what we called Lab Pages. These comprehensive and fun pages are an excel- lent way for you to see the nuances of the jQuery methods in action, without the need to write a slew of code yourself. The book assumes a fundamental knowledge of HTML, CSS, and JavaScript. A pre- vious knowledge of jQuery is not required but might come in handy to help you absorb the concepts faster. Roadmap We’ve divided the book into three parts: an introduction to jQuery and what it brings to the table, the jQuery core, where we cover all of its features, and a section on advanced topics. Licensed to Mark Watson ABOUT THIS BOOKxxvi Chapter 1 is about the philosophy behind jQuery and how it adheres to a principle called unobtrusive JavaScript. It discusses what jQuery is, what problems it tries to solve, and why you might want to employ it in your web projects. Chapter 2 covers the selection of DOM elements via the use of selectors and how to create your own custom selectors. We’ll also introduce you to the term jQuery collection (or jQuery object), which is used to refer to the JavaScript object returned by jQuery’s methods. It contains the set of elements selected on which you can operate with the library. Chapter 3 expands on chapter 2 by teaching how to refine or create a new selec- tion of elements starting with a previous selection. You’ll also learn how to create new DOM elements with jQuery. Chapter 4 focuses on the many methods jQuery offers for working with attributes and properties, and what their differences are. Moreover, it explains how to store cus- tom data on one or more DOM elements. Chapter 5 is all about manipulating element class names, cloning and setting the content of DOM elements, and modifying the DOM tree by adding, moving, or replac- ing elements. Chapter 6 introduces you to the various event models and how browsers allow you to establish handlers to control what happens when an event occurs. Then, we’ll cover how jQuery allows developers to do the same thing while avoiding dealing with browser incompatibilities. In addition, the chapter describes important notions like event delegation and event bubbling. Chapter 7 is different from the previous ones because its aim is to walk you through the development of a project, a DVD discs locator, where you can apply the lessons learned up to this point. Chapter 8 examines the methods used to show and hide elements, and how you can create animations. Function queuing for serially running effects, as well as general functions, are also covered. Chapter 9 is dedicated to utility functions, functions that are namespaced by jQuery that usually don’t operate on DOM elements. Chapter 10 covers one of the most important concepts of recent years: Ajax. We’ll see how jQuery makes it almost brain-dead simple to use Ajax on web pages, shielding us from all the usual pitfalls, while vastly simplifying the most common types of Ajax interactions (such as returning JSON objects). We set up a new challenge for you in chapter 11. Here, we’ll tackle a real-world problem that many developers face: creating a contact form. The project consists of building a working contact form that doesn’t require a complete reload of the page to inform the user about the failure or success in sending the message. Chapter 12 is the first of part 3 where we move onto advanced topics, most of which are not strictly related to the core of the library. In this chapter, we’ll discuss how to extend the functionality of jQuery by creating plugins for it. These plugins come in two flavors: methods and utility functions. In this chapter we’ll examine both of them. Licensed to Mark Watson ABOUT THIS BOOK xxvii Chapter 13 explains how to avoid what’s known as the callback hell by describing jQuery’s implementation of Promises. As you’ll learn, this is a delicate and controver- sial topic that has been the subject of discussions for years. In chapter 14 we introduce you to testing, what it is, and why it’s important. We’ll focus our attention on one particular kind of testing: unit testing. Then, we’ll cover QUnit, a JavaScript testing framework employed by some of the jQuery projects (jQuery, jQuery UI, and jQuery Mobile) to unit test the code. Chapter 15, the last chapter of the book, starts with tips and tricks to improve the performance of code that uses jQuery by selecting elements the right way. Then, we’ll broaden our focus to several tools, frameworks, and patterns not strictly related to jQuery but that can be used to craft fast, solid, and beautiful code. In particular, this chapter explains how to organize your code in modules, how to load modules with RequireJS, and how to manage front-end dependencies with Bower. Finally, we’ll give you a taste of how jQuery fits into single-page applications by skimming the surface of Backbone.js. To top it all off, we have provided an appendix highlighting key JavaScript con- cepts such as function contexts and closures—essential to make the most effective use of jQuery on our pages—for readers who are unfamiliar with, or would like a refresher on, these concepts. Source code conventions and downloads The source code in the book, whether in code listings or snippets, is in a fixed-width font like this, which sets it off from the surrounding text. In some listings, the code is annotated to point out key concepts, and numbered bullets are sometimes used in the text to provide additional information about the code. The code is formatted so that it fits within the available page space in the book by adding line breaks and using indentation carefully. All of the source code for the examples in the book can be found at this GitHub link: https://github.com/AurelioDeRosa/jquery-in-action. The source code is also available for download from the publisher’s website at www.manning.com/derosa/ or www.manning.com/jquery-in-action-third-edition. Software requirements The code examples for this book are organized in folders, one for each chapter, ready to be easily served by a local web server such as the Apache HTTP Server. With the exception of the projects built in chapters 7 and 10 and a few other ones, the exam- ples don’t require the presence of a web server and can be loaded directly into a browser for execution, if you so desire. The project in chapter 10 requires more back- end interaction than Apache can deliver, so running it locally requires setting up PHP for Apache. All examples were tested in a variety of browsers, including Internet Explorer, Fire- fox, Safari, Opera, and Chrome. Licensed to Mark Watson ABOUT THIS BOOKxxviii Author Online Purchase of jQuery in Action, Third Edition includes free access to a private web forum run by Manning Publications where you can make comments about the book, ask technical questions, and receive help from the authors and other users. To access the forum and subscribe to it, point your web browser to www.manning.com/derosa. This Author Online (AO) page provides information on how to get on the forum once you’re registered, what kind of help is available, and the rules of conduct on the forum. Manning’s commitment to our readers is to provide a venue where a meaningful dialog among individual readers and between readers and authors can take place. It’s not a commitment to any specific amount of participation on the part of the authors, whose contribution to the AO remains voluntary (and unpaid). We suggest you try ask- ing the authors some challenging questions, lest their interest stray! The AO forum and the archives of previous discussions will be accessible from the publisher’s website as long as the book is in print. About the cover illustration The figure on the cover of jQuery in Action, Third Edition is captioned “The Watch- man.” The illustration is taken from a French travel book, Encyclopédie des Voyages by J. G. St. Saveur, published almost 200 years ago. Travel for pleasure was a relatively new phenomenon at the time, and travel guides such as this one were popular, intro- ducing both the tourist as well as the armchair traveler to the inhabitants of other regions of the world, as well as to the regional costumes and uniforms of French sol- diers, civil servants, tradesmen, merchants, and peasants. The diversity of the drawings in the Encyclopédie des Voyages speaks vividly of the uniqueness and individuality of the world’s towns and provinces just 200 years ago. Isolated from each other, people spoke different dialects and languages. In the streets or in the countryside, it was easy to identify where they lived and what their trade or station in life was just by how they were speaking or what they were wearing. Dress codes have changed since then and the diversity by region, so rich at the time, has faded away. It is now often hard to tell the inhabitant of one continent from another. Perhaps, trying to view it optimistically, we have traded a cultural and visual diversity for a more varied personal life—or a more varied and interesting intellectual and technical life. We at Manning celebrate the inventiveness, the initiative, and the fun of the com- puter business with book covers based on the rich diversity of regional life two centu- ries ago, brought back to life by the pictures from collections such as this one. Licensed to Mark Watson xxix about the authors BEAR BIBEAULT has been writing software for over three decades, starting with a Tic-Tac-Toe program written on a Control Data Cyber supercomputer via a 100-baud teletype. Because he has two degrees in Electrical Engineering, Bear should be designing antennas or something; but, since his first job with Digital Equip- ment Corporation, he has always been much more fascinated with programming. Bear has also served stints with companies such as Lightbridge Inc., BMC Software, Dragon Systems, Works.com, and a handful of other companies. Bear even served in the U.S. Military teaching infantry soldiers how to blow up tanks; skills that come in handy during those daily scrum meetings. Bear is currently a senior web developer for a leading provider of object storage software. In addition to his day job, Bear also writes books (duh!), runs a small business that creates web applications and offers other media services (but not wedding videogra- phy—never, ever wedding videography), and helps to moderate JavaRanch.com as a “sheriff” (senior moderator). When not planted in front of a computer, Bear likes to cook big food (which accounts for his jeans size), dabble in photography and video, ride his Yamaha V-Star, and wear tropical-print shirts. He works and resides in Austin, Texas, a city he dearly loves, except for the com- pletely insane drivers. Licensed to Mark Watson ABOUT THE AUTHORSxxx YEHUDA KATZ has been involved in a number of open source projects over the past several years. In addition to being a core team member of the jQuery project, he is also a contributor to Merb, an alternative to Ruby on Rails (also written in Ruby). Yehuda was born in Minnesota, grew up in New York, and now lives in sunny Santa Barbara, California. He has worked on websites for the New York Times, Allure Magazine, Architectural Digest, Yoga Journal, and other similarly high-profile clients. He has programmed pro- fessionally in a number of languages including Java, Ruby, PHP, and JavaScript. In his copious spare time, he maintains VisualjQuery.com and helps answer ques- tions from new jQuery users in the IRC channel and on the official jQuery mailing list. AURELIO DE ROSA is a (full-stack) senior web developer with more than 5 years’ professional experience programming for the web using the WAMP stack and HTML5, CSS3, Sass, JavaScript, and PHP. He’s a member of the jQuery team and the JoindIn team, and an expert on JavaScript and HTML5 APIs. His interests also include web security, accessibility, performance, and SEO. When not busy writing code, he’s a regular writer, speaker, author of books, and coauthor of some academic papers. Licensed to Mark Watson Part 1 Starting with jQuery If you’re reading this page, it’s because you’ve heard of jQuery from a fellow developer or read about it in a website or forum, and you’re eager to understand what this library is all about. Maybe you’re employing this library at work and you want to improve your skills to impress your boss. Or perhaps you’ve never heard about this jQuery thing and you were just captured by the very nice illus- tration on the cover of this book. Whatever the reason that brought you to open this book and read this page, the next chapter will (hopefully) give you all the explanations you need. In the only chapter belonging to part 1, you’ll learn more about what jQuery is, what problems it tries to solve, and why you might want to employ it in your web projects. In chapter 1 we’ll teach you how to extricate yourself from the dif- ferent versions of jQuery available and decide which one best fits your needs. If you’re into web development and want to become a professional of the most used library in the world, proceed to chapter 1 and start the amazing journey that this book will be. Licensed to Mark Watson Licensed to Mark Watson 3 Introducing jQuery “There are only two kinds of languages: the ones people complain about and the ones nobody uses.” How well this sentence from Bjarne Stroustrup, who designed and implemented C++, summarizes the sentiments about JavaScript. It, as well as several other languages (most notably PHP), was bemoaned as a “bad” language for several years. Then, something magical happened. Thanks to the rise of Ajax, the release of several libraries such as Prototype, Moo Tools, and jQuery, and the new, highly interactive web applications (which you might also have heard referred to as single-page applications), developers started understanding JavaScript’s potential. Today JavaScript is also one of the most ubiquitous languages thanks to Node.js, a platform that allows you to use it as a server-side language, and PhoneGap, a frame- work for creating hybrid mobile applications. jQuery is a free (licensed under the MIT License), popular JavaScript library, created by John Resig in 2006, that’s designed to simplify the client-side scripting of HTML. As stated on the jQuery website, This chapter covers  What exactly jQuery is and why you should use it  The unobtrusive JavaScript strategy  Choosing the right version of jQuery  Fundamental elements and concepts of jQuery Licensed to Mark Watson 4 CHAPTER 1 Introducing jQuery jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers. With a combination of versatility and extensibility, jQuery has changed the way that millions of people write JavaScript. Although you might find this claim a bit self-promotional or presumptuous, it asserts nothing but the truth. jQuery has really changed the way millions of developers and designers write their code. Its use is so widespread that, according to the latest BuiltWith statistics (as of April 2015), jQuery is used by 63% of the top million websites (http://trends.builtwith.com/javascript/jQuery). The previously cited Moo Tools library, its nearest competitor, has a usage of just 3% (http://trends .builtwith.com/javascript/MooTools), while Prototype has a mere 2.5% (http:// trends.builtwith.com/javascript/Prototype). jQuery is used by some of the most important companies and websites in the world, such as Microsoft, Amazon, Dell, Etsy, Netflix, Best Buy, Instagram, Fox News, GoDaddy, and many more. If you had any doubts about jQuery, this data should con- vince you that it’s a stable and reliable library that you can use in your projects. This book covers many aspects of the library starting from basic concepts, like selectors and the methods to traverse the Document Object Model (DOM), to more advanced ones, like extending the functionalities (creating plugins), improving the performances of your code, and testing. It assumes you have a minimal knowledge of JavaScript. If you need a refresher, take a look at the appendix. If you’re unfamiliar with the language, you may find this text too tough, so we encourage you to study it and then come back. We’ll wait here. Are you back? Glad to see you again! Let’s start from the beginning—that is, dis- cussing what jQuery has to offer you and how it can help you in your web develop- ment process. 1.1 Write less, do more jQuery’s motto is “Write less, do more.” If you’ve spent any time at all trying to add dynamic functionality to your pages, you’ve found that performing simple tasks using raw JavaScript can result in dozens of lines of code (LoC). The creator of jQuery spe- cifically created this library to make common tasks trivial and easy to learn, solving issues caused by browser incompatibilities. For example, anyone who has dealt with radio groups in JavaScript knows that it’s a lesson in tedium to discover which radio element of a radio group is currently checked and to obtain its value attribute. The radio group needs to be located, and the resulting set of radio elements must be inspected, one by one, to find out which element has its checked attribute set. This element’s value attribute can then be obtained. Licensed to Mark Watson 5Write less, do more To be compatible with Internet Explorer 6 and above (if you ignore some older browsers, a better approach exists), such code might be implemented as follows: var checkedValue; var elements = document.getElementsByTagName('input'); for (var i = 0; i < elements.length; i++) { if (elements[i].type === 'radio' && elements[i].name === 'some-radio-group' && elements[i].checked) { checkedValue = elements[i].value; break; } } Contrast that with how it can be done using jQuery: var checkedValue = jQuery('input:radio[name="some-radio-group"]:checked').val(); Don’t worry if that looks a bit cryptic right now. In short order, you’ll understand how it works, and you’ll be whipping up your own terse—but powerful—jQuery statements to make your pages come alive. The point we want to show here is how the library can turn a lot of lines of code into just one. What makes the previous jQuery statement so short is the power of the selector, an expression used to identify target elements on a page. It allows you to easily locate and grab the elements that you need; in this case, the checked element in the radio group. If you haven’t downloaded the example code yet, now would be a great time to do so. It can be obtained from a link on this book’s web page at http://www.manning.com/ derosa. Unpack the code and load into your browser the HTML page that you find in the file chapter-1/radio.group.html. This page, shown in figure 1.1, uses the jQuery statement that we just examined to determine which radio button has been checked. This example shows you how simple and concise code written using jQuery can be. This isn’t the only real power of jQuery; otherwise we could have thrown it out the window a long time ago. Nonetheless, one of its great strengths is the ability to retrieve elements using complex selectors without worrying about cross-browser compatibility, especially in older browsers. When you perform a selection, you’re relying on two things: a method and a selec- tor. Today the latest versions of all major browsers support native methods for element selection like document.querySelector() and document.querySelectorAll(). They allow you to use more complex selectors instead of the usual selection by ID or class. Figure 1.1 Determining which radio button is checked is easy to accomplish in one statement with jQuery! Licensed to Mark Watson 6 CHAPTER 1 Introducing jQuery In addition, the new CSS3 selectors are widely supported among modern browsers. If you aimed to support only modern browsers, and the capabilities of jQuery lay only in selecting elements, you would have enough power to avoid the overhead introduced by the library in your website. The fact that a lot of people still rely on older browsers, which you may have to support, can be a real pain because you have to deal with all the inconsistencies. This is one of the main reasons to employ jQuery. It allows you to reliably use its selectors without the worry of code not working in browsers that don’t support them natively. NOTE If you’re wondering what browsers are considered modern today, they are Internet Explorer 10 and above and the latest versions of Chrome, Opera, Firefox, and Safari. Still not convinced? Here’s a list of issues that you’ll have to tackle on your own if you don’t use jQuery: http://goo.gl/eULyPT. In addition, as we outlined, the library is much more than that, as you’ll discover in the rest of the book. Let’s now examine how JavaScript should be used on your pages. 1.2 Unobtrusive JavaScript You may recall the bad-old days before CSS, when you were forced to mix stylistic markup with the document structure markup in your HTML pages. Anyone who’s been authoring pages for any amount of time surely does, most likely with less than fondness. The addition of CSS to your web development toolkits allows you to separate stylis- tic information from the document structure and gives travesties like the tag the well-deserved boot. Not only does the separation of style from structure make your documents easier to manage, but it also gives you the versatility to completely change the stylistic rendering of a page by swapping out different style sheets. Few of you would voluntarily regress to the days of applying styles with HTML ele- ments, yet markup such as the following is still all too common: You can easily see that the style of this button element isn’t applied via the use of the tag and other deprecated style-oriented markup. It’s determined by whatever, if any, CSS rules (not shown here) that are in effect on the page. Although this decla- ration doesn’t mix style markup with structure, it does mix behavior with structure. It includes the JavaScript to be executed when the button is clicked as part of the markup of the button element via the onclick attribute (which, in this case, changes the color of a DOM element with the ID value of xyz into red). Let’s examine how you might improve this situation. Licensed to Mark Watson 7Unobtrusive JavaScript 1.2.1 Separating behavior from structure For all the same reasons that it’s desirable to segre- gate style from structure within an HTML document, it’s just as beneficial (if not more so) to separate the behavior from the structure. Ideally, an HTML page should be structured as shown in figure 1.2, with structure, style, and behavior each partitioned nicely in its own niche. This strategy, known as unobtrusive JavaScript, is now embraced by every major JavaScript library, help- ing page authors achieve this useful separation on their pages. As the library that popularized this move- ment, jQuery’s core is well optimized for producing unobtrusive JavaScript easily. Unobtrusive JavaScript considers any JavaScript expressions or statements placed within or among HTML tags in the of HTML pages, either as attributes of HTML elements (such as onclick) or in script blocks placed any- where other than the very end of the body of the page, to be incorrect. “But how can I instrument the button without the onclick attribute?” you might ask. Consider the following change to the button element: Much simpler! But now, you’ll note, the button doesn’t do anything. You can click it all day long, and no behavior will result. Let’s fix that. 1.2.2 Segregating the script Rather than embedding the button’s behavior in its markup, you’ll segregate the script by moving it to a script block. Following the current best practices, you should place it at the bottom of the page before the closing body tag (): Because you’re placing the script at the bottom of the page, you don’t need to use a handler attached to the onload event of the window object, like developers (errone- ously) use to do in the past, or wait for the DOMContentLoaded event, which is only STYLE Local style elements and imported style sheets STRUCTURE HTML structural elements BEHAVIOR Local script elements and imported script files Figure 1.2 With structure, style, and behavior each neatly tucked away within a page, readability and maintainability are maximized. Licensed to Mark Watson 8 CHAPTER 1 Introducing jQuery available in modern browsers. The DOMContentLoaded event is fired when the HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and so on to finish loading. The load event is fired when an HTML page and its dependent resources have finished loading (we’ll return to this topic in section 1.5.3). By placing the script at the bottom of the page, when the browser parses the statement, the button element exists because its markup has been parsed, so you can safely augment it. NOTE For performance reasons, script elements should always be placed at the bottom of the document body. The first reason is to allow progressive ren- dering, and the second is to have greater download parallelization. The moti- vation behind the first is that rendering is blocked for all content below a script element. The reason behind the second is that the browser won’t start any other downloads, even on a different hostname, if a script element is being downloaded. The previous snippet is another example of code that isn’t 100% compatible with the browsers your project might be targeting. It uses a JavaScript method, addEvent- Listener(), that’s not supported by Internet Explorer 6–8. As you’ll learn later on in this book, jQuery helps you in solving this problem, too. Unobtrusive JavaScript, though a powerful technique to add to the clear separa- tion of responsibilities within a web application, doesn’t come without a price. You might already have noticed that it took a few more lines of script to accomplish your goal than when you placed it into the button markup. Unobtrusive JavaScript may increase the line count of the script that needs to be written, and it requires some dis- cipline and the application of good coding patterns to the client-side script. But none of that is bad; anything that persuades you to write your client-side code with the same level of care and respect usually allotted to server-side code is a good thing! But it is extra work—without jQuery, that is. jQuery is specifically focused on the task of making it easy and delightful for you to code your pages using unobtrusive JavaScript techniques, without paying a hefty price in terms of effort or code bulk. You’ll find that making effective use of jQuery will enable you to accomplish much more on your pages while writing less code. The motto is still “Write less, do more,” isn’t it? Without further ado, let’s start looking at how jQuery makes it so easy for you to add rich functionality to your pages without the expected pain. 1.3 Installing jQuery Now that you know what jQuery is and what it can do for you, you need to download the library to start getting your hands dirty. To download it, please visit the page http:// jquery.com/download/. Once there, you’ll probably be overwhelmed by the plethora of options available. Branch 1.x, 2.x, or 3.x? Compressed or uncompressed? Download it or use a content delivery network (CDN)? Which one to choose depends on several factors. To make a conscious choice, let’s uncover the differences. Licensed to Mark Watson 9Installing jQuery 1.3.1 Choosing the right version In April 2013, the jQuery team introduced version 2.0 with the intention of looking at the future of the web instead of its past, especially from the browser’s perspective. Until that point, jQuery supported all of the latest versions of Chrome, Firefox, Safari, Opera, and Internet Explorer starting from version 6. With the introduction of ver- sion 2.0, the team decided to leave behind the older Internet Explorer 6, 7, and 8 browsers to focus on the web as it will be, not as it was. This decision caused the deletion of a bunch of code created to solve browser incompatibilities and missing features in those prehistoric browsers. The fulfillment of this task resulted in a smaller (-12%) and faster code base. Although 1.x and 2.x are two different branches, they have a strict relation. There’s feature parity between jQuery version 1.10 and 2.0, version 1.11 and 2.1, and so on. In October 2014, Dave Methvin, the president of the jQuery Foundation (the foundation that takes care of jQuery and other projects—https://jquery.org/), pub- lished a blog post (http://blog.jquery.com/2014/10/29/jquery-3-0-the-next-genera- tions/) where he publicly announced the plan to release a new major version of jQuery: jQuery 3. In the same way version 1.x supports old browsers while 2.x targets modern browsers, jQuery 3 is split into two versions. jQuery Compat 3 is the successor of 1.x, whereas jQuery 3 is the successor of 2.x. He further explained: We’ll also be re-aligning our policy for browser support starting with these releases. The main jQuery package remains small and tight by supporting the evergreen browsers (the current and previous versions of a specific browser) that are common at the time of its release. We may support additional browsers in this package based on market share. The jQuery Compat package offers much wider browser support, but at the expense of a larger file size and potentially lower performance. With the new version, the team also took the opportunity to drop the support for some browsers, fix many bugs, and improve several features. The first factor to consider when deciding which version to use is which browsers your project must support. Table 1.1 describes the browsers supported by each major version of jQuery. Table 1.1 An overview of the browsers supported by the major versions of jQuery Browsers jQuery 1 jQuery 2 jQuery Compat 3 jQuery 3 Internet Explorer 6+ 9+ 8+ 9+ Chrome Current and previous Current and previous Current and previous Current and previous Firefox Current and previous Current and previous Current and previous Current and previous Safari 5.1+ 5.1+ 7.0+ 7.0+ Opera 12.1x Current and previous 12.1x Current and previous Current and previous Current and previous Licensed to Mark Watson 10 CHAPTER 1 Introducing jQuery As you can see from the table, there’s a certain degree of overlap in regard to the browser versions supported. But keep in mind that what’s referred to as “Current and previous” (meaning the current and preceding version of a browser at the time a new version of jQuery is released) changes based on the release date of the new version of jQuery. Another important factor to base your decision on is where you’ll use jQuery. Here are some use cases that can help you in your choice:  Websites that don’t need to support older versions of Internet Explorer, Opera, and other browsers can use branch 3.x. This is the case for websites running in a controlled environment such as a company local network.  Websites that need to target an audience as wide as possible, such as a govern- ment website, should use branch 1.x.  If you’re developing a website that needs to be compatible with a wider audi- ence but you don’t have to support Internet Explorer 6–7 and old versions of Opera and Safari, you should use jQuery Compat 3.x.  If you don’t need to support Internet Explorer 8 and below, but you have to support old versions of Opera and Safari, you should use jQuery 2.x.  Mobile apps developed using PhoneGap or similar frameworks can use jQuery 3.x.  Firefox OS or Chrome OS apps can use jQuery 3.x.  Websites that rely on very old plugins, depending on the actual code of the plu- gins, may be forced to use jQuery 1.x. In summary, two of the factors are where you’re going to use the library and which browsers you intend to support. Another source of confusion could be the choice between the compressed (also referred to as minified) version, intended for the production stage, or the uncom- pressed version, intended for the development stage (see the comparison in figure 1.3). The advantage of the minified library is the reduction in size that leads to bandwidth savings for the end users. This reduction is achieved by removing the use- less spaces (indentation), removing the code’s comments that are useful for developers but ignored by the JavaScript engines, and shrinking the names of the variables (obfus- cation). These changes produce code that’s harder to read and debug—which is why you shouldn’t use this version in development—but smaller in size. iOS 6.1+ 6.1+ 7.0+ 7.0+ Android 2.3 4.0+ 2.3 4.0+ 2.3 4.0+ 2.3 4.0+ Table 1.1 An overview of the browsers supported by the major versions of jQuery (continued) Browsers jQuery 1 jQuery 2 jQuery Compat 3 jQuery 3 Licensed to Mark Watson 11Installing jQuery In this book we’ll use jQuery 1.x as a base to let you test your code in the widest range of possible browsers, but we’ll highlight all the differences introduced by jQuery 3 so that your knowledge will be as up to date as possible. Choosing the right version of jQuery is important, but we also cited the difference between hosting jQuery locally or using a CDN. 1.3.2 Improving performances using a CDN Today it’s common practice to serve files like images and libraries through a content delivery network to improve the performance of a website. A CDN is a distributed system of servers created to offer content with high availability and performance. You might be aware that browsers can download a fixed set of contents, usually from four to eight files, from a host at the same time. Because the files served using a CDN are provided from a different host, you can speed up the whole loading process, increasing the number of files downloaded at a time. Besides, a lot of today’s websites use CDNs, so there’s a higher probability that the required library is already in the user’s browser cache. Employing a CDN to load jQuery doesn’t guarantee better performance in every situation because there are many factors that come into play. Our advice is to test which configuration best suits your specific case. Uncompressed Compressed Figure 1.3 At the top, a snippet taken from the jQuery's source code that shows you the uncompressed version format. At the bottom, the same snippet minified to be used in production. Licensed to Mark Watson 12 CHAPTER 1 Introducing jQuery Nowadays there are several CDNs you can rely on to include jQuery, but the most reliable are the jQuery CDN (http://code.jquery.com), the Google CDN (https:// developers.google.com/speed/libraries/devguide), and the Microsoft CDN (http:// www.asp.net/ajaxlibrary/cdn.ashx). Let’s say you want to include the compressed version of jQuery 1.11.3 using the jQuery CDN. You can do that by writing the following code: As you may have noticed, this code doesn’t specify the protocol to use (either HTTP or HTTPS). Instead, you’re specifying the same protocol used in your website. But keep in mind that using this technique in a page that doesn’t run on a web server will cause an error. Using a CDN isn’t all wine and roses, though. No server or network has 100% uptime on the internet, and CDNs are no exception. If you rely on a CDN to load jQuery, in the rare situations where it’s down or not accessible and the visitor’s browser doesn’t have a cached copy, your website’s code will stop working. For critical applications this can be a real problem. To avoid it, there’s a simple and smart solu- tion you can adopt, employed by a lot of developers. Once again, you want to include the minified version of jQuery 1.11.3, but now you’ll use this smart solution: The idea behind this code is to request a copy of the library from a CDN and check if it has been loaded, testing whether the jQuery property of the window object is defined. If the test fails, you inject a code that will load a local hosted copy that, in this specific example, is stored in a folder called javascript. If the jQuery property is pres- ent, you can use jQuery’s methods safely without the need to load the local hosted copy. You test for the presence of the jQuery property because, once loaded, the library adds this property. In it you can find all the methods and properties of the library. During the development process, we suggest that you use a local copy of jQuery to avoid any connectivity problems. In addition to the jQuery property, you’ll also find a shortcut called $ that you’ll see a lot in the wild and in this book. Although it may seems odd, in JavaScript a variable or a property called $ is allowed. We called $ a shortcut because it’s actually the same object of jQuery as proved by this statement taken from the source code: window.jQuery = window.$ = jQuery; So far, you’ve learned how to include jQuery in your web pages but you know nothing about how it’s structured. We’ll look at this topic in the next section. Licensed to Mark Watson 13How jQuery is structured 1.4 How jQuery is structured The jQuery repository (https://github.com/jquery/jquery), hosted on GitHub, is a perfect example of how front-end development has changed over the past years. Although not strictly related to the use of the library itself, it’s always important to know how expert developers organize their workflow and the tools they employ. If you’re an experienced front-end developer, chances are you’re already aware of some, if not all, of these tools, but a refresher is always worthwhile. The development team adopted the latest and coolest technologies in today’s front-end panorama for the development of jQuery, specifically these:  Node.js (http://nodejs.org)—A platform built on Chrome’s JavaScript runtime that enables you to run JavaScript as a server-side language.  npm (https://npmjs.org)—The official package manager for Node.js used to install packages like Grunt and its tasks.  Grunt (http://gruntjs.com)—A task runner to automate common and repeti- tive tasks such as building, testing, and minification.  Git (http://git-scm.com)—A free, distributed version control system to keep track of changes in the code. It allows easy collaboration between developers. On the other hand, jQuery’s source code follows the asynchronous module definition (AMD) format. The AMD format is a proposal for defining modules where both the module and its dependencies can be asynchronously loaded. In practice, this means that although you use jQuery as a unique, single block, its source is split into several files (modules), as shown in figure 1.4. The dependencies relative to these files are managed through the use of a dependencies manager—in this case, RequireJS. ajax ajax/xhr ajax/script ajax/jsonp css deprecated dimensions effects event jQuery event/alias offset wrap core/ready deferred Sizzleexports/ global exports/ amd Figure 1.4 A schema representing jQuery’s modules: ajax, ajax/xhr, ajax/script, ajax/jsonp, css, deprecated, dimensions, effects, event, event/alias, offset, wrap, core/ready, deferred, exports/global, exports/amd, and Sizzle Licensed to Mark Watson 14 CHAPTER 1 Introducing jQuery To give you an idea of what’s inside the modules, here are some examples:  ajax—Contains all the Ajax functions like ajax(), get(), and post().  deprecated—Contains all the currently deprecated methods that haven’t been removed. What’s inside this module depends on the jQuery version.  effects—Contains the methods that allow animations like animate() and slideUp().  event—Contains the methods to attach event handlers to browser events like on() and off(). The organization into modules of the source leads to another advantage: the possibil- ity of building a custom version of jQuery containing only the modules you need. 1.4.1 Save space creating your own custom build jQuery offers you the possibility of building your own custom version of the library, containing only the functionalities you need. This allows you to reduce the weight of your library, which will lead to a performance improvement because the end user has fewer KBs to download. The ability to eliminate the modules you don’t need is important. Although you might think that you’ll need all the power that jQuery brings to the table, it’s doubtful that you’ll use all of its functions in the same website. Why not remove those useless lines of code to improve the performance of your website? You can use Grunt to create a custom version. Imagine that you need a minified version of jQuery 1.11.3 with all the functionalities (except the deprecated methods and properties) and the effects. To perform this task, you need to install Node.js, Git, and Grunt on your local machine. After installing them, you have to clone jQuery’s repository by running the following command using the command-line interface (CLI): git clone git://github.com/jquery/jquery.git Once the cloning process is complete, enter these last two commands: npm install grunt custom:-deprecated,-effects You’re finished! Inside the folder named dist you’ll find your custom jQuery build in both minified and non-minified versions. This approach doesn’t come without drawbacks, though. The first issue arises when a new version of jQuery is released. The second arises when a new functionality of your website requires a feature contained in a module that wasn’t previously included. In these cases, you need to again perform the steps described previously (usually only the commands) to create a new custom version that includes the new methods, bug fixes, or the missing module. Now that you know how to put the library in place and how to create a custom build, it’s time to delve into jQuery’s fundamentals. Licensed to Mark Watson 15jQuery fundamentals 1.5 jQuery fundamentals At its core, jQuery focuses on retrieving elements from HTML pages and performing operations on them. If you’re familiar with CSS, you’re already well aware of the power of selectors, which describe groups of elements by their type, attributes, placement within the document, and much more. With jQuery, you can employ that knowledge and that degree of power to vastly simplify your JavaScript. jQuery places a high priority on ensuring that code will work consistently across all major browsers; many of the harder JavaScript problems have been silently solved for you. Should you find that the library needs a bit more juice, jQuery has a simple but powerful way for extending its functionality via plugins, which we’ll discuss in detail in chapter 12. Let’s start by taking a look at the jQuery object itself and how you can use your CSS knowledge to produce powerful yet terse code. 1.5.1 Properties, utilities, and methods As we said before, the jQuery library is exposed through a property called jQuery and a shortcut called $. Using them gives you access to the properties, methods, and func- tions that jQuery provides. One of the properties exposed by the jQuery property is fx.off. It allows enabling or disabling effects executed using jQuery’s methods. We’ll discuss this and other properties in detail in chapter 9. Much more exciting are the utilities, also referred to as utility functions. You can think of them as a handful of commonly used, general-purpose functions that are included in the library. You could say that jQuery acts as a namespace for them. To give you a basic idea of what they are, let’s look at an example. One of the utili- ties available is the function for trimming strings. Its aim is to remove whitespaces from the beginning and the end of a string. A call to it could look like this: var trimmed = $.trim(someString); If the value of someString is “ hello ”, the result of the $.trim() call will be “hello”. As you can see, in this example we used the jQuery shortcut ($). Remember that it’s an identifier like any other in JavaScript. Writing a call to the same function using the jQuery identifier, rather than its alias, will result in this code: var trimmed = jQuery.trim(someString); Another example of a utility function is $.isArray(), which, as you may guess, tests if a given argument is an array. In addition to properties and functions, the library also exposes methods that are available once you call the jQuery() function. Let’s learn more. 1.5.2 The jQuery object The first function you’ll use in your path to learn jQuery is jQuery(). It accepts up to two arguments, and, depending on their number and type, performs different tasks. Licensed to Mark Watson 16 CHAPTER 1 Introducing jQuery Like many other (almost all) methods in the library, it allows for chaining. Chaining is a programming technique used to call several methods in a single statement. Instead of writing var obj = new Obj(); obj.method(); obj.anotherMethod(); obj.yetAnotherMethod(); you can write var obj = new Obj(); obj.method().anotherMethod().yetAnotherMethod(); The most common use of jQuery() is to select elements from the DOM so you can apply some changes to them. In this case, it accepts two parameters: a selector and (optionally) a context. This function returns an object containing a collection of DOM elements that match the given criteria. But what’s a selector? When CSS was introduced to web technologies in order to separate design from content, a way was needed to refer to groups of page elements from external style sheets. The method developed was to use selectors, which concisely represent ele- ments based on their type, attributes, or position within the HTML document. Those familiar with XML might be familiar with XPath (more on this here: http:// www.w3.org/TR/xpath20/) as a means to select elements within an XML document. CSS selectors represent an equally powerful concept but are tuned for use within HTML pages, are a bit more concise, and are generally considered easier to under- stand. jQuery makes use of the same selectors as CSS. It supports not only the widely implemented ones belonging to CSS2.1 but also the more powerful selectors defined in CSS3. This is important because some of them may not be fully implemented by all browsers or may never make their appearance (for example, in older versions of Inter- net Explorer). As if this were not enough, jQuery also has its own selectors and allows you to create your own custom selectors. In this book you’ll be able to use your existing knowledge of CSS to get up and run- ning fast, and then you’ll learn about the more advanced selectors that jQuery sup- ports. If you have little knowledge of them, don’t worry. We’ll cover jQuery selectors in great detail in chapter 2, and you can find a full list of them on the jQuery site at http://api.jquery.com/category/selectors/. Let’s say you want to select all the

s in the page using jQuery(). To do this, you can write var paragraphs = jQuery('p'); The library searches for matching elements within the DOM starting from the docu- ment root, so for a huge number of elements the process can be slow. Licensed to Mark Watson 17jQuery fundamentals In most cases, you can speed up the search using the context parameter. It’s used to restrict the process to one or more subtrees, depending on the selector used. To understand it, you’ll modify the previous example. Let’s say that you want to find all the

s contained in a

. Contained doesn’t mean the
must be the parent of the

; it can also be a generic ancestor. You can achieve this task as shown below: var paragraphsInDiv = jQuery('p', 'div'); Using the jQuery alias, the same statement will look like this: var paragraphsInDiv = $('p', 'div'); When you use the second argument, jQuery first collects elements based on this selec- tor called context and then retrieves the descendants that match the first parameter, selector. We’ll discuss this topic in more detail in chapter 2. As we said, the jQuery() function (and its alias $()) returns a JavaScript object containing a set of DOM elements that match the selector, in the order in which they’re defined within the document. This object possesses a large number of useful predefined methods that can act on the collected group of elements. We’ll use the term jQuery collection, jQuery object, or jQuery set (or other similar expressions) to refer to this returned JavaScript object that contains the set of matched elements that can be operated on with the methods defined by jQuery. Based on this definition, the pre- vious paragraphsInDiv variable is a jQuery object containing all the paragraphs that are descendants of a div element. You’ll use jQuery objects extensively when you need to perform operations, like running a certain animation or applying a style, on several elements in the page. As mentioned earlier, one important feature of a large number of these methods, which we often refer to as jQuery methods, is that they allow for chaining. After a method has completed its work, it returns the same group of elements it acted on, ready for another action. As things get progressively more complicated, making use of jQuery’s chainability will continue to reduce the lines of code necessary to produce the results you want. In the previous section, we highlighted the advantages of placing the JavaScript code at the bottom of the page. For many years now, developers have placed the scripts elements in the of the page, relying on a jQuery method called ready(). This approach is now discouraged, but many developers still use it. In the next section you’ll learn more about it and also discover what the suggested approach is today. 1.5.3 The document ready handler When embracing unobtrusive JavaScript, behavior is separated from structure. Apply- ing this principle, you perform operations on the page elements outside the docu- ment markup that creates them. In order to achieve this, you need a way to wait until the DOM elements of the page are fully realized before those operations execute. Licensed to Mark Watson 18 CHAPTER 1 Introducing jQuery In the radio group example, the entire body has to be loaded before the behavior can be applied. Traditionally, the onload handler for the window instance is used for this purpose, executing statements after the entire page is fully loaded. The syntax is typically something like this: window.onload = function() { // do stuff here }; This causes the defined code to execute after the document has fully loaded. Unfortu- nately, the browser not only delays executing the onload code until after the DOM tree is created but also waits until all external resources are fully loaded and the page is dis- played in the browser window. This includes resources like images as well as Quick- Time and Flash videos embedded in web pages. As a result, visitors can experience a serious delay between the time that they first see the page and the time that the onload script is executed. Even worse, if an image or other resource takes significant time to load, visitors will have to wait for the image loading to complete before the rich behaviors become available. This could make the whole unobtrusive JavaScript proposition a nonstarter for many real-life cases. A much better approach would be to wait only until the document structure is fully parsed and the browser has converted the HTML into its resulting DOM tree before executing the script to apply the rich behaviors. Accomplishing this in a cross-browser manner that takes into account older browsers is somewhat difficult, but jQuery pro- vides a simple means to trigger the execution of code once the DOM tree has loaded (without waiting for external resources). The formal syntax to define such code is as follows: jQuery(document).ready(function() { // Your code goes here... }); First, you wrap the document object using the jQuery() function, and then you call the ready() method, passing a function to be executed when the document is ready to be manipulated. This means that inside the function passed to ready() you can safely access all of the elements of your page. A schema of the mechanism described is shown in figure 1.5. We called that the formal syntax for a reason; a short- hand form is as follows: jQuery(function() { // your code hoes here... }); By passing a function to jQuery() or its alias $(), you instruct the browser to wait until the DOM has fully loaded Handler executed Page downloaded HTML parsed DOM created Document ready fired Figure 1.5 A representation of the steps performed by browsers before the document-ready handler is executed Licensed to Mark Watson 19Summary (but only the DOM) before executing the code. Even better, you can use this tech- nique multiple times within the same HTML document, and the browser will execute all of the functions you specify in the order in which they’re declared within the page. In contrast, the window’s onload technique allows for only a single function. This limitation can also result in hard-to-find bugs if any included third-party code uses the onload mechanism for its own purpose (not a best-practice approach). Using the document-ready handler is a good way to embrace the unobtrusive JavaScript technique, but its use isn’t mandatory and can be avoided. Because ready() takes care to execute the code after the DOM is loaded, develop- ers used to place the script elements in the of the page. As we discussed in section 1.2.2, “Segregating the script,” you can place them just before the closing body tag (). By doing so, you can completely avoid the use of $(document) .ready() because at that point all of the other elements are already in the DOM. Therefore, you can retrieve and use them safely. If you want to see an example of how $(document).ready() can be avoided, take a look at the source code of the file chapter-1/radio.group.html. In the remainder of this book we’ll stick with the current best practices, so you won’t use ready(). 1.6 Summary We’ve covered a great deal of material in this whirlwind introduction to jQuery. To summarize, it’s generally useful for any page that needs to perform anything but the most trivial of JavaScript operations. It’s also strongly focused on enabling page authors to employ the concept of unobtrusive JavaScript within their pages. With this approach, behavior is separated from structure in the same way that CSS separates style from structure, achieving better page organization and increased code versatility. Despite the fact that jQuery introduces only two new names in the JavaScript namespace—the self-named jQuery function and its $ alias—the library provides a great deal of functionality by making that function highly versatile, adjusting the oper- ation that it performs based on the parameters passed to it. We mentioned how well the repository of the library and the code in general are organized. We also paid great attention to the several available versions of the library and their differences in order to be able to make a conscious choice. Performance is an important factor to consider, so we described the possibilities you have to reduce the added overhead to a minimum by including a library in your pages. Using CDNs and customizing the modules that you want are an amazing way to speed up the down- load of jQuery. In the chapters that follow, we’ll explore all the features that jQuery has to offer you as a web developer. We’ll begin our tour in the next chapter as you learn how to use jQuery selectors to quickly and easily identify the elements that you wish to act on. Licensed to Mark Watson Licensed to Mark Watson Part 2 Core jQuery Many years have passed since John Resig presented jQuery to the world. Fewer but still quite a few years are behind us since jQuery was only a library to manipulate the DOM. During this time jQuery has created an entire ecosystem around itself consisting of companion libraries and other projects such as these:  jQuery UI—A library consisting of a set of user interface interactions, effects, widgets, and themes to help you create amazing user interfaces  jQuery Mobile—An HTML5-based user interface system for all popular mobile device platforms, to help you create beautiful designs for mobile devices  QUnit—A JavaScript unit-testing framework used by all the other jQuery projects  Plugins—The plugins published on npm (https://www.npmjs.com/) and the myriad of other plugins spread across the web that people have cre- ated to cover those use cases not covered by jQuery or to improve its func- tionalities In part 2 of this book, we’ll cover the core library from stem to stern. When you finish these chapters, you’ll thoroughly know the jQuery library and be ready to tackle any web project armed with one of the most powerful client-side tools available. So turn the page, dig in, and get ready to learn how to breathe life into your web applications in a way that’s not only easy but fun! Licensed to Mark Watson Licensed to Mark Watson 23 Selecting elements In this chapter, we’ll examine in great detail how the DOM elements to be acted upon are identified by looking at one of the most powerful and frequently used capabilities of jQuery’s $() function: the selection of DOM elements via selectors. Throughout the pages of this chapter, you’ll become familiar with the plethora of selectors available. jQuery not only provides full support for all the CSS selectors but also introduces other ones. We’ll also introduce you to filters, many of which are special jQuery-only selectors that usually work with other types of selectors to fur- ther reduce a set of matched elements. As if this weren’t enough, you’ll learn how to create custom filters (also referred to as custom selectors or custom pseudo-selectors) in case your pages need one the library doesn’t support. We’ll also discuss context, the second parameter of the $() function, and describe the implications of its use. This chapter covers  Selecting elements with jQuery by using CSS selectors  Discovering the unique jQuery-only filters  Developing custom filters  Learning the context parameter of the jQuery() function Licensed to Mark Watson 24 CHAPTER 2 Selecting elements A good number of the capabilities required by interactive web applications are achieved by manipulating the DOM elements that make up the pages. But before they can be manipulated, they need to be identified and selected. This and the next chap- ter provide you with the concepts to select elements. In the previous edition of this book, they were a unique chapter because their contents are highly related, but we decided to split them to help you digest the huge number of concepts described. Note that, despite the split, this chapter is still pretty long and terse. You may expect to go through it several times before mastering all its concepts. With this last note in mind, let’s begin our detailed tour of the many ways that jQuery lets you specify which ele- ments are to be targeted for manipulation. 2.1 Selecting elements for manipulation The first thing you need to do when using virtually any jQuery method is to select some document elements to act upon. As you learned in chapter 1, to select elements in a page using jQuery, you need to pass the selector to the jQuery() function (or its alias $()). The jQuery() function and its alias return a jQuery object containing a set of DOM elements that match the given criteria and also expose many of jQuery’s methods and properties. Sometimes the set of elements you want to select will be easy to describe, such as “all paragraph elements on the page.” Other times they’ll require a more complex descrip- tion like “all list elements that have the class list-element, contain a link, and are first in the list.” Fortunately, jQuery provides a robust selector syntax you can use to easily specify sets of elements elegantly and concisely. You probably already know a big chunk of the syntax. jQuery uses the CSS syntax you already know and love and extends it with some custom means to perform both common and complex selections. To help you learn about element selection, we’ve put together a jQuery Selectors Lab Page that’s available in the downloadable code examples for this book (in the file chapter-2/lab.selectors.html). The Selectors Lab allows you to enter a jQuery selector string and see (in real time!) which DOM elements get selected. When displayed, the lab should look as shown in figure 2.1. TIP If you haven’t yet downloaded the example code, you really ought to do so now—the information in this chapter will be much easier to absorb if you follow along with the lab exercises. Visit this book’s web page at http:// www.manning.com/derosa to find the download link, or go to https://github .com/AurelioDeRosa/jquery-in-action. The Selector Panel at the top left contains a text box and a button. To run a lab “experiment,” type a selector into the text box and click the Apply button. Go ahead and type the string li into the box and click Apply. The selector that you type (in this case li) is applied to the HTML fragment loaded into the DOM Sample pane at the upper right. The lab code that executes when you click Apply adds a class named found-element to all the matching elements. A CSS declaration defined for the page causes all elements with that class to be highlighted Licensed to Mark Watson 25Selecting elements for manipulation with a black border and gray background. After clicking Apply, you should see the dis- play shown in figure 2.2, in which all li elements in the DOM sample are highlighted. In addition, the executed jQuery statement, as well as the tag names of the selected elements, is displayed below the Selector text box. The HTML markup used to render the DOM sample fragment is displayed in the lower pane, labeled “DOM Sample Code.” This should help you experiment with writing selectors targeted at the ele- ments in this sample. Figure 2.1 The jQuery Selectors Lab Page allows you to observe the behavior of any selector you choose in real time. Licensed to Mark Watson 26 CHAPTER 2 Selecting elements We’ll talk more about using this lab as we progress through the chapter. For the moment, let’s take a look at how jQuery deals with the basic CSS selectors. 2.2 Basic selectors For applying styles to page elements, web developers have become familiar with a small but useful group of selection expressions that work across all browsers. Those expressions can select by an element’s ID, by CSS class names, and by tag names. A spe- cial case of selecting elements by tag name is the Universal selector, which allows you to select all the page elements within the DOM. The selection expressions enable you to perform basic searches in the DOM, and we’ll provide the details in the following sections. When combined, these selectors allow you to achieve slightly more compli- cated selections. Table 2.1 provides a quick refresher of these selectors and how you can combine them. Table 2.1 Some simple CSS selector examples Example Description In CSS? * Matches all the elements in the page ✓ #special-id Matches the element with the ID value of special-id ✓ .special-class Matches all elements with the class special-class ✓ Matched elements Matched elements highlighted jQuery command executed Figure 2.2 A selector value of li matches all li elements when applied, as shown by the displayed results. Licensed to Mark Watson 27Basic selectors In JavaScript, you have a set of functions, such as getElementById() and get- ElementsByClassName(), that are designed to work with a specific type of selector to retrieve DOM elements to act upon. Unfortunately, you might have some problems using even such simple functions. For example, getElementsByClassName() isn’t sup- ported in versions of Internet Explorer prior to 9. If you want to use only native meth- ods, you should pay attention to cross-browser compatibilities. jQuery to the rescue! If the browser supports the selector or the function natively, jQuery will rely on it to be more efficient; otherwise it’ll use its methods to return the expected result. The good news is that you don’t have to worry about this difference. jQuery will do its work for you behind the scenes, so you can focus on other aspects of your code. The jQuery library is fully CSS3 compliant, so selecting elements will present no surprises; the same elements that would be selected in a style sheet by a standards- compliant browser will be selected by jQuery’s selector engine. The library does not depend on the CSS implementation of the browser it’s running within. Even if the browser doesn’t implement a standard CSS selector correctly, jQuery will correctly select elements according to the rules of the World Wide Web Consortium (W3C) standard. For some practice, play with the Selectors Lab and run some experiments with some basic CSS selectors until you feel comfortable with them. Happy to know that jQuery will solve all the cross-browser compatibilities (for the supported browsers) for us, we can now delve into the plethora of selectors available. 2.2.1 The All (or Universal) selector The first selector available is the All (or Universal) selector, which is represented by an asterisk (*). As the name suggests, it allows you to retrieve all of the DOM elements of a web page, even the head element and its children. To reinforce this concept, let’s say you have the following HTML page: jQuery in Action, 3rd edition a Matches all anchor (a) elements ✓ a.special-class Matches all anchor (a) elements that have the class special-class ✓ .class.special-class Matches all elements with the class class and class special-class ✓ Table 2.1 Some simple CSS selector examples (continued) Example Description In CSS? Licensed to Mark Watson 28 CHAPTER 2 Selecting elements

I'm a paragraph

To retrieve all the elements of the page you need to use the Universal selector and pass it to the jQuery() function (or its alias $()) in a statement like the following: var allElements = $('*'); Before moving on, there’s an established convention we want to mention. When sav- ing the result of a selection made with jQuery in a variable, a widely adopted conven- tion is to prepend or (less commonly) append a dollar sign to the name of the variable. It doesn’t have a special meaning; it’s used as a reminder of what the variable is storing. Another reason to adopt one of these conventions is to be sure not to invoke $() on a set of DOM elements on which we’ve already called this method. For example, you may erroneously write the following: var allElements = $('*'); // Other code here... $(allElements); Using the aforementioned conventions, you can rewrite the previous statement prepending the dollar sign to the variable name, as shown here: var $allElements = $('*'); Alternatively, you also can write it this way: var allElements$ = $('*'); We recommend adopting one of these conventions and sticking with it. Throughout the rest of the book, we’ll use the first one: the dollar sign prepended. Let’s now see the first complete example of using jQuery in a web page. In this example, shown in listing 2.1, we’ll use a CDN to include jQuery using the fallback technique learned in chapter 1, and the Universal selector to select all the elements of the page. You can find the code for this listing in the file chapter-2/listing-2.1.html in the source provided with the book. In the remainder of the book, the examples will only include a reference to a local version of the jQuery library, avoiding the use of any CDN. There are two main reasons for this choice: brevity (that is, writing less code) and avoiding an additional HTTP request (that fails if you’re running the exam- ples while offline). jQuery in Action, 3rd edition

I'm a paragraph

Listing 2.1 Using the Universal selector with jQuery Request jQuery from the jQuery CDN. Licensed to Mark Watson 29Basic selectors We told you that the previous listing was created to select all the elements of the page, but what are these elements? If you inspect the variable using a debugger or with the help of the console (where available), you’ll see that they are html, head, title, body, p, script (the first in the page), and script (the second in the page). WARNING We want to point out that the console.log() method is not sup- ported by old versions of Internet Explorer (IE 6–7). In the examples in this book we’ll ignore this issue and we’ll use this method heavily to avoid resort- ing to the very annoying window.alert() method. But you should keep in mind this lack of support in case your code needs to work in these browsers. Remember, the elements are retrieved and stored in the same order in which they appear on the page. As you’ve seen, the use of the All selector forces jQuery to traverse all of the DOM’s nodes. With a lot of elements in the DOM, the process might be very slow; therefore its use is discouraged. In addition, it’s unlikely that you’ll need to retrieve all the ele- ments of a page, although you could need to collect those belonging to a specific sub- tree of the DOM, as you’ll see later. If you’ve ever played with JavaScript and a browser, you know that one of the most- used selections is performed using the ID of a given element. Let’s discover more about this topic. Fall back to a local copy if the CDN is unavailable. Select all the elements in the page. Developer tools Trying to develop a DOM-scripted application without the aid of a debugging tool is like trying to play concert piano while wearing welding gloves. Why would you do that to yourself? Depending on the browser you’re using, there are different options you can choose to inspect your code. All major modern browsers have a set of built-in tools for this purpose, although with a different name, that you can adopt. For example, in Chrome these tools are called the Chrome Developer Tools (https://developers.google.com/ chrome-developer-tools/), whereas in Internet Explorer they’re called the F12 devel- oper tools (http://msdn.microsoft.com/en-us/library/bg182326(v=vs.85).aspx). Firefox has its own built-in tools as well, but developers usually use a plugin called Firebug (http://getfirebug.com). These tools not only let you inspect the JavaScript console, but they also allow you to inspect the live DOM, the CSS, the scripts, and many other aspects of your page as you work through its development. Licensed to Mark Watson 30 CHAPTER 2 Selecting elements 2.2.2 The ID selector The ID selector is one of the most used selectors, not only in jQuery but also in plain JavaScript. In JavaScript, to select an element by its ID, you pass the ID to the native document.getElementById() function. If you have some knowledge of CSS, you’ll recall that the ID selector is characterized by a sharp (#) sign (in some countries this symbol is known with a different name like number sign or pound sign) prepended to the element’s ID. If you have this paragraph in your page

jQuery in Action is a book about jQuery

you can retrieve it using the ID selector and jQuery by writing $('#description'); When used with the ID selector, jQuery returns a collection of either zero or one DOM element. In case you have more than one element on a page with the same ID, the library retrieves only the first matched element encountered. Although you can have more than one element with the same ID, it’s invalid and you should not do that. NOTE The W3C specifications of HTML5 assert that the value of an ID “must not contain any space characters. There are no other restrictions on what form an ID can take; in particular, IDs can consist of just digits, start with a digit, start with an underscore, consist of just punctuation, etc.” It’s possible to use characters such as the period (.) that have a special meaning in CSS and jQuery (because it follows the CSS conventions). Because of this, they must be escaped by prepending two backslashes to the special character. Thus, if you want to select an element with ID of .description, you have to write $('#\\.description'). It isn’t accidental that we compared how to select elements by their ID in jQuery and in JavaScript at the beginning of this section, using the getElementById() function. In jQuery the selection by ID is the fastest one, regardless of the browser used, because behind the scenes the library uses getElementById(), which is very fast. Using the ID selector you’re able to quickly retrieve one element in the DOM. Often, you need to retrieve elements based on the class names used. How can you select elements that share the same style? 2.2.3 The Class selector The Class selector is used to retrieve elements by the CSS class names used. As a JavaScript developer, you should be familiar with this kind of selection through the use of the native getElementsByClassName() function. jQuery follows the CSS con- ventions, so you have to prepend a dot before the chosen class name. For example, if you have the following HTML code inside the of a page

A title

I'm a paragraph

Licensed to Mark Watson 31Basic selectors

Another title

I'm yet another paragraph

and you want to select the elements that have the class description, you need to pass .description to the $() function by writing the following statement: var $descriptions = $('.description'); The result of this statement is an object, often referred to by the documentation as a jQuery object or a jQuery collection (other names you can find in the wild are set of matched elements, or simply set or collection) containing the two paragraphs of the HTML snippet. The library will also select the nodes having multiple classes where one of them matches the given name (like the second paragraph). In jQuery, like in CSS, it’s also possible to combine more class name selectors. If you want to select all the elements having the classes description and blue, you can concatenate them, resulting in $('.description.blue'). The Class selector is surely one of the most used among JavaScript and CSS, but there’s another basic selector we still need to discuss. 2.2.4 The Element selector The Element selector allows you to pick up elements based on their tag name. Because of its support in almost any browser (including IE6), jQuery uses get- ElementsByTagName() to select elements by tag name behind the scenes. To under- stand what kind of selection you can perform with the Element selector, let’s say you want all the
s in a page. To achieve this task, you have to write var $divs = $('div'); It’s common to use it in conjunction with other selectors because you’ll usually have a lot of elements of the same type in your pages. In such cases, it must be written before the other selectors. Hence, if you want all
s having class clearfix, you have to write the following statement: var $clearfixDivs = $('div.clearfix'); You can also combine it with the ID selector, but we strongly encourage you to not do that for two reasons: performance and usefulness. Using a complex selector, jQuery will perform a search using its own methods, usually avoiding the use of native func- tions, and this leads to slower execution. In addition, as we pointed out in the section on the ID selector, jQuery will retrieve the first (if any) element having the searched ID. Therefore, if you’re searching for just one element, there’s no need to add com- plexity to your selector by mixing two types. jQuery also enables you to use different types in a single selection, providing a per- formance gain because the DOM is traversed only once. To use it, you have to add a comma after each selector but the last one (spaces after the comma are ignored, so Licensed to Mark Watson 32 CHAPTER 2 Selecting elements their use is a matter of code style). To select all the
s and the s in a page, you can write $('div, span'); In case a given element matches more than one of the comma-separated selectors (which is not possible when you use only Element selectors because, for example, an element is a div or a span), the library will retrieve it only once, removing all the duplicates for you. Thanks to the selectors discussed in these sections, you’re able to perform basic searches in the DOM. But you often need to select elements using more complex crite- ria. You may need to retrieve DOM nodes based on their relation with other nodes like “all the links inside an unordered list.” What you’re doing here is specifying a selec- tion based on the hierarchy of the elements. How to perform such a search is the topic of the next section. 2.3 Retrieving elements by their hierarchy Retrieving a set of elements by their class name is a nice feature, but often you don’t want to search the whole page. Sometimes you may want to select only the direct chil- dren of a certain element. Consider the following HTML fragment from the sample DOM in the Selectors Lab: Suppose that you wanted to select the a element pointing to the jQuery website but not those to various local pages describing the different CSS specifications. To achieve this goal you can use the Child selector, in which a parent and its direct child are sepa- rated by the right angle bracket character (>). You can write ul.my-list > li > a This selector will collect only links that are direct children of list elements, which are in turn direct children of the
    that have class my-list. The links contained in the sublists are excluded because the ul element serving as their parent doesn’t have the class my-list. Running this selector in the lab page gives the result shown in figure 2.3. Licensed to Mark Watson 33Retrieving elements by their hierarchy The Child selector isn’t the only one available to express a relation between two or more elements based on the DOM tree’s hierarchy. Table 2.2 provides an overview of the selectors of this type. All the selectors described in the table but the first one are part of the CSS2.1 specifica- tions, so they aren’t supported by Internet Explorer 6. But you can use all of them safely in jQuery because the library deals with these kinds of problems for you. Table 2.2 The CSS hierarchy selectors supported by jQuery Selector Description In CSS? E F Matches all elements with tag name F that are descendants of E ✓ E>F Matches all elements with tag name F that are direct children of E ✓ E+F Matches all elements with tag name F that are immediately preceded by sibling E ✓ E~F Matches all elements with tag name F preceded by any sibling E ✓ Figure 2.3 With the selector ul.my-list > li > a, only the direct children of parent nodes are matched. Licensed to Mark Watson 34 CHAPTER 2 Selecting elements These selectors improved your ability to precisely target the DOM nodes you want to act upon. Over time a lot of other CSS selectors have been created to place more power in your hands. One of the features introduced was the ability to select elements based on their attributes. These selectors are the topic of the next section. 2.4 Selecting elements using attributes Attribute selectors are extremely powerful and allow you to select elements based on their attributes. You can easily recognize these selectors because they’re wrapped with square brackets (for example, [selector]). To see them in action, let’s take another look at a portion of the lab page: What usually makes the link pointing to an external site unique is the http:// at the beginning of the string value for the link’s href attribute. Actually, an external link may also be prefixed by https://, ftp://, and many other protocols. Besides, a link pointing to a page of the same website might still start with http://. But for the sake of simplicity we’ll take into account http:// only and we’ll pretend that internal links use only relative paths. In CSS, you could select links that have an href value starting with http:// with the following selector: a[href^='http://'] Using jQuery, the latter can be employed in a statement like the following: var $externalLinks = $("a[href^='http://']"); This matches all links with an href value beginning with the exact string http://. The caret character (^) is used to specify that the match has to occur at the beginning of a value. Because this is the same character used by most regular expression processors to signify matching at the beginning of a candidate string, it should be easy to remember. Visit the lab page again (from which the previous HTML fragment was lifted), type a[href^='http://'] into the text box, and click Apply. Note that only the jQuery link is highlighted. Licensed to Mark Watson 35Selecting elements using attributes Now imagine you want all the links but those pointing to the jQuery website’s home- page. Using our lovely library, you can write $("a[href!='http://jquery.com']") This statement, using the “not equal attribute” selector, gives you the expected result. Because this selector isn’t part of the CSS specifications, behind the scenes jQuery can’t take advantage of the native querySelectorAll() method, so this results in a slower execution. These symbols can’t be combined with other ones to create even more powerful selectors. For example, if you want to select all links but the externals (assuming only those starting with http://), you can’t write $("a[href!^='http://']"); At this point you may think that selecting elements by their attribute is possible only in conjunction with the Element selector. But this isn’t the case. You can use whatever selector you like, and even no other selectors at all, resulting in a selector like [href^='http://']. In this case, the use of the Universal selector (*) is implicitly assumed. There are other ways to use attribute selectors. To match an element—for exam- ple, a form—that possesses a specific attribute, regardless of its value, you can use form[method] This matches any
    that has an explicit method attribute. To match a specific attribute value, you use something like input[type='text'] This selector matches all input elements with a type of text. You’ve already seen the “match attribute at beginning” selector in action. Here’s another example: div[title^='my'] This selects all div elements with a title attribute whose value begins with my. Single and double quotes Pay attention to single and double quotes when you use the attribute selectors. A wrong combination of the latter will result in an invalid statement. If your style of code adopts the use of double quotes for strings and you want to use the same quotes for wrapping the attributes value, you must escape them. If you feel it’s easier for you to read a selection without escaped characters, you can mix the quote types. Using the selector a[href^="http://"] will result in the following equivalent statements: $("a[href^=\"http://\"]"); $('a[href^=\'http://\']'); $("a[href^='http://']"); $('a[href^="http://"]'); Licensed to Mark Watson 36 CHAPTER 2 Selecting elements What about an “attribute ends with” selector? Coming right up: a[href$='.pdf'] This is a useful selector for locating all links that reference PDF files. And here’s a selector, called “attribute contains,” for locating elements whose attri- butes contain arbitrary strings anywhere in the attribute value: a[href*='jquery.com'] As you’d expect, this selector matches all a elements that reference the jQuery site. Another selector is the “contain prefix.” It selects elements with a given attribute’s value equal to a specified string or equal to a specified string followed by a hyphen. If you write div[class|='main'] this selector will find all the
    s having class="main" or having a class name start- ing with main-, like class="main-footer". The last selector we’re going to discuss is similar to the previous one, except it’s used to search for a word within an attribute’s value. Let’s say you’re using the HTML5 data-* attribute—for example, data-technologies—to specify a list of values in some s of your page. You want to perform a search to find if one of them contains the value "javascript". You can perform this selection using the following selector: span[data-technologies~="javascript"] This selects s having an attribute like data-technologies="javascript" but also data-technologies="jquery javascript qunit". You can think of it as the equivalent of the Class selector but for a generic attribute. The presented selectors can also be chained in case you need to retrieve nodes that match more criteria. You can chain as many selectors as you like; there isn’t a fixed limit. For example, you can write input[type="text"][required] This selector retrieves all the s that are required (the required attribute has been introduced in HTML5) and are of type text. Table 2.3 summarizes the CSS selectors that deal with attributes that you can use in jQuery. With all this knowledge in hand, head over to the jQuery Selectors Lab Page and spend some more time running experiments using selectors of various types from table 2.3. Try to make some targeted selections like the input element having the type of checkbox and the value of 1 (hint: you’ll need to use a combination of selec- tors to get the job done). Selectors aren’t used only to retrieve elements using the $() function. As you’ll dis- cover later in this chapter, they’re one of the most used parameters to pass to jQuery’s methods. For example, once you’ve made a selection, you can use a jQuery method and a new selector to add new elements to the previous set or to filter some elements. Licensed to Mark Watson 37Introducing filters Another case is to find all the descendants of the elements in a previous stored set that match a given selector. As if the power of the selectors that we’ve discussed so far isn’t enough, there are some more options that offer an even finer ability to slice and dice the DOM. In the next sec- tion we’ll introduce other types of selectors known as filters. In the CSS specification these types of selectors are referred as pseudo-classes. 2.5 Introducing filters Filters are selectors that usually work with other types of selectors to reduce a set of matched elements. You can recognize them easily because they always start with a colon (:). Just as you’ve seen for the attributes, if another selector isn’t specified, the use of the Universal selector is implicitly assumed. One of the peculiarities of these selectors is that some of them accept an argument passed inside the parentheses; for example, p:nth-child(2). In the next sections, we’ll discuss all the available filters in jQuery broken down into different categories. Table 2.3 The attribute selectors supported by jQuery Selector Description In CSS? E[A] Matches all elements with tag name E that have attribute A of any value ✓ E[A='V'] Matches all elements with tag name E that have attribute A whose value is exactly V ✓ E[A^='V'] Matches all elements with tag name E that have attribute A whose value starts with V ✓ E[A$='V'] Matches all elements with tag name E that have attribute A whose value ends with V ✓ E[A!='V'] Matches all elements with tag name E that have attribute A whose value doesn’t match V (are not equal to V) or that lack attribute A completely E[A*='V'] Matches all elements with tag name E that have attribute A whose value contains V ✓ E[A|='V'] Matches all elements with tag name E that have attribute A whose value is equal to V or to V- (V followed by a hyphen) ✓ E[A~='V'] Matches all elements with tag name E that have attribute A whose value is equal to V or contains V delimited by spaces ✓ E[C1][C2] Matches all elements with tag name E that have attributes that sat- isfy the criteria C1 and C2 ✓ Licensed to Mark Watson 38 CHAPTER 2 Selecting elements 2.5.1 Position filters Sometimes you’ll need to select elements by their position on the page. You might want to select the first or last link on the page or from the third paragraph. jQuery supports mechanisms for achieving these specific selections. For example, consider a:first This format of selector matches the first on the page. Now, let’s say you want to retrieve links starting from the third one on the page. To achieve this goal, you can write a:gt(1) This selector is really interesting because it gives us the chance to discuss a few points. First, we’re using a selector called Greater than (gt) because there isn’t one called Greater than or equal. Also, unlike the selectors you’ve seen so far, it accepts an argu- ment (1 in this case) that specifies the index from which to start. Why do you pass 1 if you want to start from the third element? Shouldn’t it be 2? The answer comes from our programming background where indexes usually start at 0. The first element has index 0, the second has index 1, and so on. These selectors specific to jQuery provide surprisingly elegant solutions to some- times tough problems. See table 2.4 for a list of these Position filters (which the jQuery documentation collocates inside the basic filters category). As we noted, the first index in a set of elements is always 0. For this reason, the :even selector will counterintuitively retrieve the odd-positioned elements because of their Table 2.4 The Position filters supported by jQuery Selector Description In CSS? :first Selects the first match within the context. li a:first returns the first anchor that’s a descendant of a list item. :last Selects the last match within the context. li a:last returns the last anchor that’s a descendant of a list item. :even Selects even elements within the context. li:even returns every even-indexed list item. :odd Selects odd elements within the context. li:odd returns every odd- indexed list item. :eq(n) Selects the nth matching element. :gt(n) Selects elements after the nth matching element (the nth element is excluded). :lt(n) Selects elements before the nth matching element (the nth element is excluded). Licensed to Mark Watson 39Introducing filters even indexes. For example, :even will collect the first, third, and so on elements of a set because they have even indexes (0, 2, and so on). The takeaway lesson is :even and :odd are related to the index of the elements within the set, not their position. Another fact to highlight is that you can also pass to :eq(), :gt(), and :lt() a negative index. In this case the elements are filtered counting backward from the last element. If you write p:gt(-2), you’re collecting only the last paragraph in the page. Considering that the last paragraph has index -1, the penultimate has index -2, and so on, basically you’re asking for all the paragraphs that come after the penultimate. In some situations you don’t want to select only the first or last element in the whole page but each first or last element relative to a given parent in the page. Let’s discover how. 2.5.2 Child filters We said that jQuery embraces the CSS selectors and specifications. Thus, it shouldn’t be surprising that you can use the child pseudo-classes introduced in CSS3. They allow you to select elements based on their position inside a parent element. Where the lat- ter is omitted, the Universal selector is assumed. Let’s say you want to retrieve ele- ments based on their position inside a given element. For example, ul li:last-child selects the last child of parent elements. In this example, the last
  • child of each
      element is matched. You may also need to select elements of a type only if they’re the fourth child of a given parent. For example, div p:nth-child(4) retrieves all

      s inside a

      that are the fourth child of their parent element. The :nth-child() pseudo-class is different from :eq() although they’re often confused. Using the former, all the children of a containing element are counted, regardless of their type. Using the latter, only the elements corresponding to the selec- tor attached to the pseudo-class are counted, regardless of how many siblings they have before them. Another important difference is that :nth-child() is derived from the CSS specifications; therefore it assumes the index starts from 1 instead of 0. Another use case we can think of is “retrieve all the second elements having class description inside a
      .” This request is accomplished using the selector div .description:nth-of-type(2) As you’re going through this section you should realize that the available selectors are many and powerful. Table 2.5 shows all the Child filters described so far and many more. Please note that when a selector allows for more syntaxes, like :nth- child(), a check mark in the In CSS? column of table 2.5 means that all the syntaxes are supported. Licensed to Mark Watson 40 CHAPTER 2 Selecting elements As table 2.5 points out, :nth-child(), :nth-last-child(), :nth-last-of-type(), and :nth-of-type() accept different types of parameters. The parameter can be an index, the word “even,” the word “odd,” or an equation. The latter is a formula where you can have an unknown variable as n. If you want to target the element at any posi- tion that’s a multiple of 3 (for example 3, 6, 9, and so on), you have to write 3n. If you need to select all the elements at a position that’s a multiple of 3 plus 1 (like 1, 4, 7, and so on), you have to write 3n+1. Because things are becoming more complicated, it’s best to see some examples. Consider the following table from the lab’s sample DOM. It contains a list of program- ming languages and some basic information about them: Table 2.5 The Child filters of jQuery Selector Description In CSS? :first-child Matches the first child element within the context ✓ :last-child Matches the last child element within the context ✓ :first-of-type Matches the first child element of the given type ✓ :last-of-type Matches the last child element of the given type ✓ :nth-child(n) :nth-child(even|odd) :nth-child(Xn+Y) Matches the nth child element, even or odd child elements, or nth child element computed by the supplied formula within the context based on the given parameter ✓ :nth-last-child(n) :nth-last-child(even|odd) :nth-last-child(Xn+Y) Matches the nth child element, even or odd child elements, or nth child element computed by the supplied formula within the context, counting from the last to the first element, based on the given parameter ✓ :nth-of-type(n) :nth-of-type(even|odd) :nth-of-type(Xn+Y) Matches the nth child element, even or odd child elements, or nth child element of their parent in relation to siblings with the same element name ✓ :nth-last-of-type(n) :nth-last-of-type(even|odd) :nth-last-of-type(Xn+Y) Matches the nth child element, even or odd child elements, or nth child element of their parent in relation to siblings with the same element name, counting from the last to the first element ✓ :only-child Matches the elements that have no siblings ✓ :only-of-type Matches the elements that have no siblings of the same type ✓ Licensed to Mark Watson 41Introducing filters
      Language Type Invented
      Java Static 1995
      Ruby Dynamic 1993
      Smalltalk Dynamic 1972
      C++ Static 1983
      Let’s say that you wanted to get all of the table cells that contain the names of pro- gramming languages. Because they’re all the first cells in their rows, you could use #languages td:first-child You could also use #languages td:nth-child(1) but the first syntax would be considered pithier and more elegant. To grab the language type cells, you’d change the selector to use :nth-child(2), and for the year they were invented, you’d use :nth-child(3) or :last-child. If you wanted the absolute last table cell (the one containing the text 1983), you’d use the :last pseudo-class seen in the previous section, resulting in td:last. To test your ability, you can imagine another situation. Let’s say that you want to retrieve the name of the languages and their year of creation using :nth-child(). Basically, what you’re asking here is to take for each table row () the first and the third columns (). The first and easier solution is to pass odd as the argument to the filter, resulting in #languages td:nth-child(odd) Just to have some more fun, let’s make the previous selection harder, assuming that you want to perform the same selection passing a formula to the :nth-child() filter. Recalling that the index for :nth-child() starts at 1, you can turn the previous selec- tor into #languages td:nth-child(2n+1) Licensed to Mark Watson 42 CHAPTER 2 Selecting elements This last example should reinforce in you the idea that jQuery puts great power in your hands. Before we move on, head back over to the Selectors Lab and try selecting entries two and four from the list. Then try to find three different ways to select the cell con- taining the text 1972 in the table. Also try to get a feel for the difference between the :nth-child() type of filters and the absolute position selectors. Even though the CSS selectors we’ve examined so far are incredibly powerful, we’ll discuss ways of squeezing even more power out of jQuery’s selectors that are specifi- cally designed to target form elements or their status. 2.5.3 Form filters The CSS selectors that you’ve seen so far give you a great deal of power and flexibility to match the desired DOM elements, but there are even more selectors that give you greater ability to filter the selections. As an example, you might want to match all check boxes that are in a checked state. You might be tempted to try something along these lines: $('input[type="checkbox"][checked]'); But trying to match by attribute will check only the initial state of the control as speci- fied in the HTML markup. What you really want to check is the real-time state of the controls. CSS offers a pseudo-class, :checked, that matches elements that are in a checked state. For example, whereas the input[type="checkbox"] selector selects all input elements that are check boxes, the input[type="checkbox"]:checked selector narrows the search to only input elements that are check boxes and are currently checked. When rewriting your previous statement to select all the check boxes that are currently checked using the filter, you can write $('input[type="checkbox"]:checked'); jQuery also provides a handful of powerful custom filter selectors, not specified by CSS, that make identifying target elements even easier. For example, the custom :checkbox selector identifies all check box elements. Combining these custom selec- tors can be powerful and shrink your selectors even more. Consider rewriting once again our example using filters only: $('input:checkbox:checked'); As we discussed earlier, jQuery supports the CSS filter selectors and also defines a number of custom selectors. They’re described in table 2.6. Table 2.6 The CSS and custom jQuery filter selectors Selector Description In CSS? :button Selects only button elements (input[type=submit], input[type=reset], input[type=button], or button) Licensed to Mark Watson 43Introducing filters These CSS and custom jQuery filter selectors can be combined, too. For example, if you want to select only enabled and checked check boxes, you could use $('input:checkbox:checked:enabled'); Try out as many of these filters as you like in the Selectors Lab Page until you feel that you have a good grasp of their operation. These filters are an immensely useful addition to the set of selectors at your dis- posal, but did you think, even for one moment, that the selectors ended here? No way! 2.5.4 Content filters Another of the categories that you can find in the jQuery documentation is the one containing Content filters. As the name suggests, these filters are designed to select ele- ments based on their content. For example, you can choose elements if they contain a given word or if the content is completely empty. Note that by content we mean not only raw text but also child elements. As you saw earlier, CSS defines a useful selector for selecting elements that are descendants of specific parents. For example, this selector :checkbox Selects only check box elements (input[type=checkbox]) :checked Selects check boxes or radio elements in the checked state or options of select elements that are in a selected state ✓ :disabled Selects only elements in the disabled state ✓ :enabled Selects only elements in the enabled state ✓ :file Selects only file input elements (input[type=file]) :focus Selects elements that have the focus at the time the selector is run ✓ :image Selects only image input elements (input[type=image]) :input Selects only form elements (input, select, textarea, button) :password Selects only password elements (input[type=password]) :radio Selects only radio elements (input[type=radio]) :reset Selects only reset buttons (input[type=reset] or button[type=reset]) :selected Selects only option elements that are in the selected state :submit Selects only submit buttons (button[type=submit] or input[type=submit]) :text Selects only text elements (input[type=text]) or input without a type specified (because type=text is the default) Table 2.6 The CSS and custom jQuery filter selectors (continued) Selector Description In CSS? Licensed to Mark Watson 44 CHAPTER 2 Selecting elements div span will select all span elements that are descendants of div elements. But what if you wanted the opposite? What if you wanted to select all
      s that contained span elements? That’s the job of the :has() filter. Consider this selector div:has(span) which selects the div ancestor elements as opposed to the span descendant elements. This can be a powerful mechanism when you get to the point where you want to select elements that represent complex constructs. For example, let’s say that you want to find which table row contains a particular image element that can be uniquely identified using its src attribute. You might use a selector such as this $('tr:has(img[src="puppy.png"])'); which would return any table row element containing the identified image anywhere in its descendant hierarchy. A complete list of the Content filters is shown in table 2.7. If you’re starting to feel overwhelmed by all these selectors and filters, we suggest that you take a small break, because you aren’t finished yet! 2.5.5 Other filters You’ve seen an incredible number of selectors and filters (special selectors) that you probably didn’t even know existed. Your journey into the world of selectors hasn’t ended, and in this section we’ll discuss the remaining ones. A couple of them, :visible and :hidden, are categorized in the library’s documentation under Visibility filters, but for brevity we decided to include them here. If you want to negate a selector—let’s say to match any input element that’s not a check box—you can use the :not() filter. For example, to select non–check box input elements, you could use input:not(:checkbox) But be careful! It’s easy to go astray and get some unexpected results! Table 2.7 The Content filters supported by jQuery Selector Description In CSS? :contains(text) Selects only elements containing the specified text (the text of the children and the descendants is also evaluated). :empty Selects only elements that have no children (including text nodes). ✓ :has(selector) Selects only elements that contain at least one element that matches the specified selector. :parent Selects only elements that have at least one child node (either an element or text). Licensed to Mark Watson 45Introducing filters Let’s say that you wanted to select all images except those whose src attribute con- tained the text dog. You might quickly come up with the following selector: $(':not(img[src*="dog"])'); But if you used this selector, you’d find that not only did you get all the image ele- ments that don’t reference dog in their src, but in general, every element in the DOM that isn’t an image element with such src attribute’s value! Whoops! Remember that when a base selector is omitted, it defaults to the Univer- sal selector. Your errant selector actually reads as “fetch all elements that aren’t images that reference ‘dog’ in their src attributes.” What you intended was “fetch all image elements that don’t reference ‘dog’ in their src attributes,” which would be expressed like this: $('img:not([src*="dog"])'); Again, use the lab page to conduct experiments until you’re comfortable with how to use the :not() filter to invert selections. When working with jQuery it’s common to use its methods to hide one or more elements on a page. To retrieve these elements you can use the :hidden filter. An ele- ment is considered hidden not only if it has display: none; applied but also if it doesn’t occupy space. For example, a hidden element is also one that has its width and height set to zero. Using this selector input:hidden you’re targeting all the input elements of the page that are hidden. When creating web pages, you often use foreign words. If you write correct, semantic HTML, you’ll find yourself tagging those words using the em element, adding the lang attribute to specify the language. Let’s say that you have a page about pizza; you could have markup like the following:

      The first pizza was called Margherita, and it was created in Napoli (Italy).

      You can select all those foreign words of this example using the :lang() filter in this way: var $foreignWords = $('em:lang(it)'); jQuery 3: Feature changed jQuery 3 slightly modifies the meaning of the :visible (and therefore of :hidden) filter. Starting from jQuery 3, elements will be considered :visible if they have any layout boxes, including those of zero width and/or height. For example, br elements and inline elements with no content will now be selected by the :visible filter. Licensed to Mark Watson 46 CHAPTER 2 Selecting elements A complete list of the remaining filters is shown in table 2.8. Although jQuery offers an incredible number of selectors, it doesn’t cover all the pos- sible use cases, and the development team behind the library knows it. For this reason, they gave you the option to create your own filters. Let’s look at how you can do this. 2.5.6 How to create custom filters In the previous sections, you learned all the selectors and filters supported by jQuery. Regardless of their number, you may deal with use cases not covered. You may also find yourself doing the same selection and then the same filtering on the retrieved set over and over again, using loops and selection constructs. In situations like these you can create a shortcut to collect nodes of the DOM or, to better phrase it, you can cre- ate a custom filter (also referred as a custom selector or custom pseudo-selector). In jQuery there are two ways to create a custom filter. The first is simpler to write but its use is discouraged because it has been replaced, starting from jQuery 1.8, by the sec- ond one. In this book we’ll describe the newer method only, but if you want to take a look at the old way, we’ve prepared a JS Bin just for you (http://jsbin.com/ImIboXAz/ edit?html,js,console,output). The example is also available in the file chapter-2/ custom.filter.old.html of the source provided with this book. Keep in mind that when using the new approach, you’re developing a custom filter that won’t work in versions of jQuery prior to 1.8. However, this shouldn’t be a problem in many cases as this ver- sion is obsolete. To explain the new way to create a custom filter, we’ll start with an example. Pre- tend you’re developing a tech game where you have a list of levels to complete with a certain grade of difficulty, the number of points the user can earn, and a list of tech- nologies to employ to complete it. Your hypothetical list could resemble this: Table 2.8 The remaining filters supported by jQuery Selector Description In CSS? :animated Selects only elements that are currently under animated control :header Selects only elements that are headers:

      through

      :hidden Selects only elements that are hidden :lang(language) Selects elements in a specified language ✓ :not(selector) Negates the specified selector ✓ :root Selects the element that’s the root of the document ✓ :target Selects the target element indicated by the fragment identifier of the document’s URI ✓ :visible Selects only elements that are visible Licensed to Mark Watson 47Introducing filters
      • Level 1
      • Level 2
      • Level 3
      • Level 4
      Now imagine you often need to retrieve levels (data-level) higher than 2 but only if they allow you to earn more than 100 points (data-points) and have jQuery in the list of the technologies to employ (data-technologies). Using the knowledge you’ve acquired so far, you know how to search li elements having the word jquery inside the attribute data-technologies (li[data-technologies~="jquery"]). But how do you perform a number comparison using selectors? The truth is you can’t. To accomplish this task, you must loop over your initial selection and then retain only the elements you need, as shown here: var $levels = $('.levels li[data-technologies~="jquery"]'); var matchedLevels = []; for(var i = 0; i < $levels.length; i++) { if ($levels[i].getAttribute('data-level') > 2 && $levels[i].getAttribute('data-points') > 100) { matchedLevels.push($levels[i]); } } Instead of repeating these lines every time, you can create a custom filter: $.expr[':'].requiredLevel = $.expr.createPseudo(function(filterParam) { return function(element, context, isXml) { return element.getAttribute('data-level') > 2 && element.getAttribute('data-points') > 100; }; }); As you can see, a filter is nothing but a function added to a property called :, which belongs to jQuery’s expr attribute. That’s no mistake, dear reader. It’s a property called “colon.” The latter is a property containing jQuery’s native filters, and you can use it to add your own. You call your custom filter requiredLevel, and instead of passing the function directly, you use a jQuery utility (actually it belongs to the underlying Sizzle selectors engine) called createPseudo() B. Initial selection using the attribute selector Loop over the matched set of elements. Test if the current element matches the requirements.Add to the final set of elements. Declare the filter using the createPseudo() function. B Return the anonymous function called to perform the tests.C Tests the current element. D Licensed to Mark Watson 48 CHAPTER 2 Selecting elements To the createPseudo() function, you pass an anonymous function where you declare a parameter called filterParam. The name of the latter, standing for “filter parameter,” is arbitrary and you can choose a different one if you prefer. This parame- ter represents an optional parameter you can pass to the filter, just like filters such as :eq() and :nth-child(), that you won’t use for the moment. Inside this anonymous function, you create another anonymous function that will be returned and that’s responsible for performing the filtering. To this inner function, jQuery passes the ele- ments to be processed one at a time (element parameter), the DOMElement or DOMDocument from which selection will occur (context parameter), and a Boolean that specifies if you’re working on an XML document or not (isXML parameter) C. Inside the innermost function, you write the code to test whether the element should be kept or not D. In your case, you test whether the level is higher than 2 and the points the user can earn are more than 100. In the previous example, we introduced an argument called filterParam that you can use to pass a parameter to your custom filter. Due to the fixed nature of our requirements, we didn’t use it. Let’s have some fun seeing how it can help you. Imagine you want to retrieve levels based on the offered number of points—some- thing like “select all the levels with a number of points higher than X.” That big X is a good opportunity to use a parameter to pass to your pseudo-selector. Based on this requirement, you can create a new filter: $.expr[':'].pointsHigherThan = $.expr.createPseudo(function(filterParam) { var points = parseInt(filterParam, 10); return function(element, context, isXml) { return element.getAttribute('data-points') > points; }; }); There are a few differences compared to the previous example. You use the create- Pseudo() function as before, but you call the filter pointsHigherThan. Before declar- ing the second function, you need to save the argument in a variable called points B so it’ll be available in its closure (if you don’t know what a closure is, read the section on closures in the appendix). At this point, you can use the given argument through the use of the stored variable C. Let’s put this new filter into action. If you want to retrieve all the levels that allow you to earn more than 50 points, you can write var $elements = $('.levels li:pointsHigherThan(50)'); obtaining the last two list items. Both the custom filters presented in this section are available in the file chapter-2/ custom.filter.html and also as a JS Bin (http://jsbin.com/mucigo/edit?html,js,console ,output). Cache argument to be available in the inner function's closure.B CUse the cached argument in the test. Licensed to Mark Watson 49Enhancing performances using context So far, you’ve used half the power of the jQuery() function used to select elements because you used just one of the two parameters you can pass. It’s time to fix this. 2.6 Enhancing performances using context Up to this point, we’ve been acting as if there were only one argument that we can pass to jQuery’s $() function, but this was just a bit of hand waving to keep things sim- ple at the start. In chapter 1 we briefly introduced a second parameter called context. It’s used to restrict the selection to one or more subtrees of the DOM, depending on the selector used. This argument is helpful when you have a large number of elements in a page because it can narrow down the subtree(s) where jQuery will perform the second phase of the search. As you’ll see with many of jQuery’s methods, when an optional argument is omit- ted, a reasonable default is assumed. And so it is with context. When a selector is passed as the first parameter, context defaults to document, applying that selector to every element in the DOM tree. That’s often exactly what you want, so it’s a nice default. But there may be times when you want to limit your search to a subset of the entire DOM. In such cases, you can identify a subset of the DOM that serves as the root of the subtree to which the selector is applied. The Selectors Lab offers a good example of this scenario. When that page applies the selector that you typed into the text field, the selector is applied only to the subset of the DOM that’s loaded into the DOM Sample pane. You can use a DOM element reference as context but also a string that contains a jQuery selector or a jQuery collection. (Yes, that means that you can pass the result of one $() invocation to another—don’t let that make your head explode yet; it’s not as confusing as it may seem at first.) When a selector or jQuery collection is provided as context, the identified ele- ments serve as the context for the application of the selector. Because there can be multiple such elements, this is a nice way to provide disparate subtrees in the DOM to serve as the context for the selection process. Let’s take the lab page as an example. We’ll assume that the selector string is stored in a variable conveniently named selector. When you apply this submitted selector, you want to apply it only to the sample DOM, which is contained within a div element with an ID of sample-dom. If you were to code the call to the jQuery function like this $(selector); the selector would be applied to the entire DOM tree, including the form in which the selector was specified. That’s not what you want. What you want is to limit the selec- tion process to the subtree of the DOM rooted at the div element with the ID of sample-dom; so instead you write $(selector, '#sample-dom'); Licensed to Mark Watson 50 CHAPTER 2 Selecting elements which limits the application of the selector to the desired portion of the DOM. When you use context, jQuery first retrieves elements based on it and then selects the descendants that match the selector provided as the first argument. In other words, you search for elements that match selector that need to have context as their ancestor. Therefore, the Descendant selector can be replaced by the use of context. Consider the following selection where you select the

      s inside a

      : $('div p'); It can be turned into $('p', 'div'); giving the same result. With this section we’ve completed the discussion of jQuery selectors. We know how hard it has been to go through all these selectors, and you shouldn’t feel discouraged. Take your time to absorb the described concepts, and when you feel ready, move on. Before we look at the methods of chapter 3, we’ll test your skills with some exer- cises focused on the concepts described so far. 2.7 Testing your skills with some exercises In this section you’ll practice doing some exercises targeting the selectors and the fil- ters described in this chapter. If you want to test your solutions, you can run them using the jQuery Selectors Lab Page. In addition, we’ll provide you our solutions to allow you to compare them with yours. 2.7.1 Exercises Here’s the list of exercises: 1 Select all the links in the page. 2 Select all the direct child links of a
      having the class wrapper. 3 Select all the links and the paragraphs that have as their ancestor a
      . 4 Select all the s that have the attribute data-level equal to hard but not the attribute data-completed equal to true. 5 Select all the elements on the page having the class name wrapper without using the class selector. 6 Select the third list item inside the list having the ID list, at any level. 7 Select all the list items (li) inside the list having the ID list, after the second. 8 Select the paragraphs that are the multiple of 3 plus 1 (1, 4, 7, and so on) child of their parent, having the class description. 9 Select the s of type password only if they’re required (required attri- bute of HTML5) and are the first child of a . 10 Select all the
      s in the page that have no children, have an odd position (hint: not index!), and don’t have the class wrapper. 11 Create a custom filter to select elements having only numbers, letters, or the underscore (_) as their text. Licensed to Mark Watson 51Summary 2.7.2 Solutions Here’s the list of solutions: 1 $('a') 2 $('div.wrapper > a') 3 $('div a, div p') or even better, using the context parameter, $('a, p', 'div') 4 $('span[data-level="hard"][data-completed!="true"]') 5 $('[class~="wrapper"]') 6 $('#list li:eq(2)') or even better $('li:eq(2)', '#list') 7 $('li:gt(1)', '#list') 8 $('p.description:nth-child(3n+1)') 9 $('input[required]:password:first-child', 'form') 10 $('div:empty:even:not(.wrapper)') 11 $.expr[":"].onlyText = $.expr.createPseudo(function(filterParam) { return function(element, context, isXml) { return element.innerHTML.match(/^\w+$/); } }); How did you do? Do you feel comfortable with the ideas outlined so far? Good! With this section we’ve completed the overview of the selectors available and how you can create your own. 2.8 Summary This chapter focused on creating and adjusting sets of elements (referred to in this chapter and beyond as a jQuery collection or set of matched elements) via the many means that jQuery provides for identifying elements on an HTML page. jQuery provides a versatile and powerful set of selectors, patterned after the selec- tors of CSS, for identifying elements within a page document in a concise but powerful syntax. These selectors include the CSS3 syntax currently supported by most modern browsers. jQuery not only supports all the CSS selectors but also expands them with its own set of selectors, offering you even more expressive power to collect elements in a web page. As if this wasn’t enough, jQuery is so flexible that it also allows you to create your own filters. In this chapter we covered all the selectors available in jQuery. In the next chapter we’ll take a look at how to use the $() function to create new HTML elements. You’ll also discover methods that accept a selector as a parameter to perform some opera- tions on a set of matched elements. Licensed to Mark Watson 52 Operating on a jQuery collection In this chapter you’ll discover how to create new DOM elements using the highly flexibile jQuery() function. The need to create new elements will occur frequently in your practice with the library. You’ll find yourself using this capability especially when we start discussing how to inject external data into a web page using JSON and the XML format and jQuery’s methods to work with Ajax. In addition, you’ll learn other methods that are different from jQuery(). We’ll divide these methods into two parts. First, we’ll describe the methods that, starting from a jQuery collection, accept a selector as a parameter to create a new set of ele- ments. For example, you’ll see a method that, starting from a set, creates a new set containing all the children of the elements in the initial set, optionally filtered using the selector passed as its argument. Then we’ll cover methods that aren’t strictly related to selectors but that allow you to iterate over the elements in a set or perform a test on them. Let’s get started! This chapter covers  Creating and injecting new HTML elements in the DOM  Manipulating a jQuery collection  Iterating over the elements of a jQuery collection Licensed to Mark Watson 53Generating new HTML 3.1 Generating new HTML On many occasions, you’ll want to generate new fragments of HTML to insert into a page. Such dynamic elements could be as simple as extra text you want to display or as complicated as creating a table of database results you’ve obtained from a server. A typical situation where this feature comes in handy is when you need to fetch external data, usually served as JSON or XML, using Ajax. With jQuery, creating dynamic elements is a simple matter. You can create a jQuery object containing DOM elements on the fly by passing to the $() function a string that contains the HTML markup for those elements. Consider this line: $('
      Hello
      '); This expression creates a new jQuery object containing a div element that’s ready to be added to the page (at this point it isn’t injected in the DOM). Any jQuery method that you could run on a set of existing elements can be run on the newly created HTML fragment. This may not seem impressive at first glance, but when you throw event handlers, Ajax, and effects into the mix (as you will in the upcoming chapters), you’ll discover how powerful it is. Note that if you want to create an empty div element, you can get away with this shortcut: $('
      '); This is identical to $('
      ') and $('
      '), although it’s highly recom- mended that you use well-formed markup and include the opening and closing tags for any element types that can contain other elements. From a performance perspec- tive these three alternatives are equivalent, as you can see from the benchmark shown in figure 3.1 (live test at http://jsperf.com/jquery-create-markup/4). Figure 3.1 A benchmark comparing the three ways of creating a new element using jQuery(). It proves that they are equivalent from a performance point of view in almost every browser. Licensed to Mark Watson 54 CHAPTER 3 Operating on a jQuery collection It’s easy to create such simple HTML elements, and thanks to the chainability of jQuery methods, creating more complex elements isn’t much harder. You can apply any jQuery method to the jQuery collection containing the newly created element. You could also create attributes on the element with jQuery’s attr() method (we’ll cover that in a later chapter), but jQuery provides an even better means to do so. In the previous chapter we introduced you to the context parameter of the $() function. When creating a new element with the $() function, you use the context parameter to specify the attributes and their values for the element you’re creating in the form of a JavaScript object. The properties of such an object serve as the name of the attributes to be applied to the element, whereas the values serve as the values of the attributes. Let’s say that you want to create an img element complete with multiple attributes and make it clickable to boot. Take a look at the code in the following listing. $('', { src: 'images/little.bear.png', alt: 'Little Bear', title:'I woof in your general direction', click: function() { alert($(this).attr('title')); } }) .appendTo('body'); The single jQuery statement in the listing creates the basic img element B; gives it important attributes using the second parameter, such as its source, alternate text, and flyout title C; and attaches it to the DOM tree (as a child of the body element) E. In the example shown, you append the element to the DOM using jQuery’s appendTo() method. We haven’t covered this method yet but it appends the elements in the jQuery collection—in this case only the newly created image—to the element specified in the argument, which in our example is the body element. We’re also throwing a bit of a curve ball at you here. In this example you also use the second parameter to establish an event handler that issues an alert (garnered from the image’s title attribute) when the image is clicked D. Regardless of how you arrange the code, that’s a pretty hefty statement—which is spread across multiple lines and with logical indentation for readability—but it also does a heck of a lot. Such statements aren’t uncommon in jQuery-enabled pages, and if you find it a bit overwhelming, don’t worry. We’ll cover every method used in this statement over the next few chapters. Writing such compound statements will be sec- ond nature before too long. Listing 3.1 Dynamically creating a full-featured img element Creates the basic img elementB Assigns various attributesCEstablishes the click handler D Add the element to the DOM by appending it at the end of the body element. E Licensed to Mark Watson 55Managing the jQuery collection Figure 3.2 shows the result of this code, both when the page is first loaded (3.2a) and after the image has been clicked (3.2b). The full code for this example can be found in the book’s project code at chapter-3/listing-3.1.html. Up until now, you’ve applied methods to the entire set of matched elements, but there may be times when you want to further manipulate that set before acting upon it. 3.2 Managing the jQuery collection Once you have a jQuery set, whether identified from existing DOM elements with selectors or created as new elements using HTML snippets (or a combination of both), you’re ready to manipulate those elements using the powerful set of jQuery methods. We’ll start looking at those methods in the next chapter, but what if you want to fur- ther refine the jQuery set? In this section, we’ll explore the many ways that you can refine, extend, or filter the jQuery set that you wish to operate upon. In order to help you in this endeavor, we’ve included another lab in the download- able project code for this chapter: the jQuery Operations Lab Page (chapter-3/ lab.operations.html). This page, which looks a lot like the Selectors Lab we employed in chapter 2, is shown in figure 3.3. This new lab page not only looks like the Selectors Lab, but it also operates in a similar fashion. But in this lab, rather than typing a selector, you can type in any com- plete jQuery operation that results in a jQuery collection. The operation is executed in the context of the DOM Sample, and, as with the Selectors Lab, the results are displayed. Figure 3.2a Creating complex elements on the fly(including this image, which generates an alert when it’s clicked) is easy as pie. Figure 3.2b The dynamically generated image possesses all expected styles and attributes, including the mouse click behavior of issuing an alert. Licensed to Mark Watson 56 CHAPTER 3 Operating on a jQuery collection NOTE This lab page loads the elements upon which it acts inside an iframe. Due to the security restrictions of some browsers, this operation may fail. To avoid this issue, you can either execute the page under a web server like Apache, Tomcat, or IIS or search for a specific solution for your browser. For example, in WebKit-based browsers, you can run them through the command-line interface (CLI) using the flag --allow-file-access-from- files. It’s important that the command creates a new process, so it must not open a new tab but a new window. Figure 3.3 The jQuery Operations Lab Page lets you compose jQuery collections in real time to help you see how collections can be created and managed. Licensed to Mark Watson 57Managing the jQuery collection The jQuery Operations Lab allows you to enter any expression that results in a jQuery set. Because of the way jQuery chaining works, this expression can also include jQuery methods, making this a powerful lab for examining the operations of jQuery. Be aware that you need to enter valid syntax, as well as expressions that result in a jQuery set. Otherwise, you’re going to be faced with a handful of unhelpful JavaScript errors. To get a feel for the lab, load it in your browser and enter this text into the Opera- tion field: $('img').hide(); Then click the Execute button. This operation is executed within the context of the DOM Sample, and you’ll see how the images disappear from the sample. After any operation, you can restore the DOM Sample to its original condition by clicking the Restore button. Although we haven’t treated it yet, the hide() method belongs to jQuery, and you’ll see it in detail later in this book. For the moment, what you need to know is that this function allows you to hide all the elements in a set. We used it because we wanted to give you a concrete example of what you can do in the Operations Lab Page. You’ll see this new lab in action as you work your way through the sections that follow, and you might even find it helpful in later chapters to test var- ious jQuery operations. 3.2.1 Determining the size of a set We mentioned before that a jQuery set acts a lot like an array. This mimicry includes a length property, just like JavaScript arrays, that contains the number of elements in the jQuery collection. Let’s say you want to know the number of all the paragraphs in your page and show it on the screen; you can write the following statement: alert($('p').length); Okay, so now you know how many elements you have. What if you want to access them directly? 3.2.2 Obtaining elements from a set Once you have a jQuery set, you often use jQuery methods to perform some sort of operation upon it as a whole. There may be times when you want a direct reference to an element or elements to perform raw JavaScript operations upon them. Let’s look at some of the ways that jQuery allows you to do just that. FETCHING ELEMENTS BY INDEX Because jQuery allows you to treat a jQuery collection as a JavaScript array, you can use simple array indexing to obtain any element in the list by position. For example, to obtain the first element in the set of all s with an alt attribute on the page, you could write var imgElement = $('img[alt]')[0]; Licensed to Mark Watson 58 CHAPTER 3 Operating on a jQuery collection The most observant of you might have noticed that we didn’t prepend the dollar sign ($) in front of the variable name (imgElement). We didn’t forget it. This jQuery set contains an array of DOM elements, so if you retrieve a single element, it isn’t a jQuery set made of one element itself but a plain DOM element. If you prefer to use a method rather than array indexing, jQuery defines the get() method for that purpose. The fragment var imgElement = $('img[alt]').get(0); is equivalent to the previous example that used array indexing. The get() method also accepts a negative index. Using get(-1) will retrieve the last element in the set, get(-2) the second to last, and so on. In addition to obtaining a single element, get() can also return an array of all the elements of the set if used without a parameter. Sometimes you’ll want a jQuery object containing a specific element rather than the plain element itself. It would look weird (although valid) to write something like this: $($('p').get(2)) For this purpose, jQuery provides the eq() method. The latter mimics the action of the :eq() selector filter discussed in the previous chapter. To see their differences in terms of code, let’s say you want to select the second element in a set containing all the
      s of a page. Here’s how you can perform this task, reporting the alternatives side by side: var $secondDiv = $('div').eq(1); var $secondDiv = $('div:eq(1)'); Method syntax: get get([index]) Obtains one or all of the matched elements in the set. If no parameter is specified, all elements in the jQuery object are returned as a JavaScript array. If an index parameter is provided, the indexed element is returned. index can be negative, in which case the count is performed starting from the end of the matched set. Parameters index (Number) The index of the single element to return. If omitted, the entire set is returned as an array. If a negative integer is given, the count starts from the end of the set. If the index is out of bounds, which is less than the negative number of elements or equal to or greater than the number of elements, the method returns undefined. Returns A DOM element, or an array of DOM elements, or undefined. Selecting using the eq() method Selecting using the :eq() filter Licensed to Mark Watson 59Managing the jQuery collection The difference between the statements is minimal, but for performance reasons (more details in chapter 15) it’s better to stick with the first form (the eq() method). As a rule of thumb, we suggest you use methods over filters because they usually lead to better performance. Now that we’ve highlighted the difference between the method and the filter, it’s time to dive into the details of the former. Obtaining the first element of a set is such a common operation that there’s a conve- nience method that makes it even easier: the first() method. The first() method has its filter counterpart in the :first filter. Once again, we want to show an example of the two alternatives. Say that you want to retrieve the first paragraph of the page; you can write one of the following: var $firstPar = $('p').first(); var $firstPar = $('p:first'); Not surprisingly, the difference in terms of code is minimal, but the first() method should be preferred to the :first filter. Method syntax: eq eq(index) Obtains the indexed element in the set and returns a new set containing just that element. Parameters index (Number) The index of the single element to return. A negative index can be specified to select the element starting from the end of the set. Returns A jQuery collection containing one or zero elements. Method syntax: first first() Obtains the first element in the set and returns a new set containing just that element. If the original set is empty, so is the returned set. Parameters none Returns A jQuery collection containing one or zero elements. Selecting using the first() method Selecting using the :first filter Licensed to Mark Watson 60 CHAPTER 3 Operating on a jQuery collection As you might expect, there’s a corresponding method to obtain the last element in a set as well, which is the counterpart of the :last filter. If you want to practice with these methods, you can use the jQuery Operations Lab Page. For example, if you want to retrieve the first list item of the list shown in the page, you can write $('li', '.my-list').first(); Now let’s examine the other method to obtain an array of elements in the set. FETCHING ALL THE ELEMENTS AS AN ARRAY If you wish to obtain all of the elements in a jQuery object as a JavaScript array of DOM elements, jQuery provides the toArray() method. Consider this example: var allLabeledButtons = $('label + button').toArray(); This statement collects all the