If you have fast machine and recent Google Chrome or Safari installed, please check a bit more "moving" version of that presentation

Otherwise, scroll down to see the slides

jQuery Best Parts

David Souther

Hello, and thank you for attending this presentation.

We've seen a couple presentations in the past couple months about some of the various javascript frameworks.

I'd like to take the time to present some of the outstanding features of jQuery, a library I've come to love for its ease of use and expressiveness.

I would like to make clear now that I am not advocating jQuery as superior or better than any other particular library- I know both Ext and Dojo well enough to say they are also excellent toolkits, but they take a very different approach to web development than jQuery.

Instead, I'd simply like to describe some of jQuery's philosophy, and show how it handles some of the common aspects of Javascript development.

Write Less, Do More

WRITE LESS, DO MORE

We are all aware that more lines of code means more things that can go wrong.

Expressive

Fewer lines do more, concisely

The jQuery approach seeks to reduce the number of lines of code you need to write, so that each expression does as much as it can correctly.

Functional

Closures for data hiding
Method Chaining

jQuery embraces the functional aspect of javascript- the API encourages data hiding through functional closures, with low-level features to mitigate and eliminate memory leak issues between DOM and the Javascript garbage collectors.

jQuery strongly encourages and utilizes method chaining to make statements both more concise and more expressive.

Semantic

MVC is DOM, CSS, jQuery

The most important part of the jQuery philosophy, though, is the semantics of the MVC model jQuery uses.

The DOM is the model, CSS is the view, and jQuery is the controller- one language for each domains.

As I grasped this approach, I became enamoured with jQuery.

Language Features

Let's move on to actual code that uses jQuery. I've pulled four useful features you'll see over and over again both in jQuery code, and other javascript libraries.

$.each (object)

http://jsfiddle.net/southerd/pnybn/

We'll start with a couple specific examples of jQuery's each iterator.

The method is considered static as {dollar}{dot}{each}, and it takes something to iterate over and a function to apply on each iteration.

It can iterate both objects and arrays- here, we're looking at an object first.

For an object, the iterator function function can take two parameters.

The first parameter is the key; the second is the value.

Also, by default, inside the iterator function the {this} context is set to the value.

In this example we have an object storing our officers on board the Enterprise D, keyed by the position they serve.

Our iterator function uses {this} for the value, and so only specifies the name of the first parameter, the key.

[[Switch to Result tab]]

When we run it, we get about what we'd expect.

Any questions about this code?

$.each (array)

http://jsfiddle.net/southerd/88hC6/

In this second example, we have an array of crewmembers.

Since cremembers are a bit more fluid in where they serve, I've just given them a department rather than an actual position.

In this example, I use both parameters for the key and value.

Notice when iterating over an array, the {key} parameter contains the numerical index in the array.

[[Switch to Result tab]]

Again, we get just what we'd expect.

Any questions on this code?

$.proxy

http://jsfiddle.net/southerd/mXGjf/

Something Javascript has a little problem with is getting the {this} context correct in asynchronous callbacks and returned functions.

This is a problem because the {this} context is set when calling a function, not when creating the function.

To get around this, Javascript itself has {Function}{dot}{apply}.

Scope can also be handled by a {self} variable within a closure that points to the correct context.

Functional languages have a more robust (and in my opinion readable) concept of functional currying- that is, a function that takes a function while returning a function which controls how the input function is called.

In Dojo this is {hitch}; here in jQuery, we call it {proxy}.

Notice the differences in the code here- we're setting up a jQuery plugin, so when these functions get called {this} will refer to the array of elements matched by the jQuery selector.

We then use {window}{dot}{setInterval} to prepare a function to call at each timeout.

When this function gets called, it will be at the top of a new call stack and {this} will be bound to the window.

In the first example, we use {dollar}{dot}{proxy} to wrap our function with jQuery magic to handle the context correctly.

In the second example, we handle the situation using a variable bound in the closure.

These are both patterns I've seen over and over in javascript libraries- neither is necessarily better, but I find the {proxy} example to be more readable.

I'm not going to run this, but it does again what you'd expect: it's an exact standin for the deprecated <blink> tag.

Any questions on this example?

$.extend (mixin)

http://jsfiddle.net/southerd/563Dc/

One common complaint developers often have with jQuery is a difficulty in code reuse.

I think this is more a problem in developers not understanding how to correctly use javascript extension patterns, and instead try and shoehorn incompatible pieces of Java into their class hierarchies.

While javascript prototypes can be difficult to manage, jQuery provides an excellent tool with {dollar}{dot}{extend}.

In this first example, we're going to use {extend} as a mixin; that is, we're going to add all the features of an abstract object to an instantiated object.

In this case, we have a constructor for a starship which just assigns a registry so we can find it in the fleet.

That's pretty useless without a warp core to get around, so we define WarpCore as an object with our methods we need.

On line 20 we build the Enterprise, using {dollar}{dot}{extend} to give it an appropriate warp core. We then test it, getting up to warp 8 for a bit before settling down to a good cruising speed of warp 5.

The mixin pattern of extension is very similar to using an abstract base implementation of an interface in Java, except that here we can have several interfaces, each with their own abstract interface, and include them as needed.

An alternative in java is having one abstract base class that implements every interface possible.

Any questions here?

$.widget (inheritance)

http://jsfiddle.net/southerd/ETt2L/

Extend as a function is fairly simple, it just merges several objects together.

To get inheritance, we want to use {dollar}{dot}{widget} from jquery ui.

The name is a bit of a misnomer at first blush- widgets and plugins in jQuery are not necessarily for wider consumption, but just overloaded words to describe modular pieces of code here.

This will require pulling in the jQuery UI project in addition to the jQuery project, but there are quite a few components in UI that we'll cover in a bit and you may want anyway.

This is one of the longer examples I have, but most is fairly self-explanatory.

The Green here defines an object that will become the prototype for our widget.

It maintains a list of colors, and sets an element's background color.

Here, we use {dollar}{dot}{widget} to create a widget with this prototype.

The {ui} is a namespace, and the {colorer} is the method we'll be calling.

This colorer is fairly bland, though- it doesn't really do anything except set around waiting for its setter to get called.

We're going to extend this widget and add mouse functionality to it, so whenever someone drags their mouse on this widget, it will change colors.

Next we'll use {dolor}{dot}{extend} to create a new prototype.

We use {extend} to copy all the new functions in this object, and all the fields on colorer's prototype, into a new object.

Then we make another call to {dolor}{dot}{widget} to create our mouseified widget.

Notice here we use an extra argument to UI's mouse helper.

This defines a variety of useful mouse related functions we can attach to.

Let's take a moment and look a bit closer at this ColorerMouse.

{underscore}{init} is a lifecycle function in the Widget framework that acts as a constructor- it gets called every time a new widget is create.

Destroy is the same, but for object descruction.

Inside of these, we use {Function}{dot}{call} to call the base class' init and destroy since we overwrote them with the {extend} call, and don't want to lose what those do.

mouseStart and mouseDrag are stub functions from {ui}{dot}{mouse} to override, as we've done.

We then make two instances of this widget, one the default green; the other we pass in an array of reds.

[[Click to results tab]]

Here, we can see the mouse events.

$.deferred

We're going to shit gears now and talk about asynchronous events in Javascript.

Most commonly asynchronous behaviors in javascript are implemented by accepting a single callback function.

The {deferred} concept is something that's come up more recently as an extension on a single callback.

In short, a {deferred} gives the developer an asynchronous thread of execution in their Javascript program.

Chain multiple callbacks

Without {deferred}s, APIs that wanted to do something asynchronously would take a callback function, which would get executed at some point after an event had finished.

This is very brittle, since only a single function can get executed at a time.

With {deferred}s, we return an object that handles adding several callbacks, which will get executed in order at the appropriate time.

Treats synchronous and asynchronous events consistently

jQuery provides an incredibly powerful extension on top of this called {when} which allows a developer to treat both synchronous and asynchronous events consistently, which we'll see in a moment.

Most expressive Deferred implementation

Google Closure: Poor API naming
Dojo: when takes single event
Ext: Doesn't exist

First, a side-trip through why jQuery has the best deferred implementation today.

Google Closure's deferred API has a very awkward naming system compared to jQuery's.

Dojo has the same problem with API naming (though they've improved it quite a bit), but still doesn't have the expressivity of jQuery's {when} syntax.

Finally, I haven't seen anything like this in Ext.

$.deferred

http://jsfiddle.net/southerd/ZWxzA/

So, that was a lot of theoretical and historical talk.

A code example here will show off some of these things I'm talking about.

What we've got here is an API to cache AJAX requests.

What we're going to do is write a function that takes a URL, and returns a deferred that will get executed when the URL's data is available.

To reduce network traffic, it's going to only look up any URL a single time.

There is a lot that gets done in a very few lines of code, so I'm going to go through line by line.

First, lines 1 and 13 are our functional closure to keep our data private; notice the use of the module pattern .

Inside this closure, we declare the cache, and for example's sake give it some default data.

Jumping ahead, lines 10 through 12 should be pretty clear- just a utility function to show us what's in the cache at that time.

The really interesting code here is the xhrCache function, lines 3 through 9.

The body is a single statement, using the short-circuit {or} operator.

If the URL is in the cache, that value gets returned immediately.

Otherwise, it calls jQuery's {get} function, which does an ajax get to the given URL and returns a {deferred} object.

The {deferred} object has a function {then} which does all the magic of this callback chaining.

{then} takes a function, registers it to get called when the deferred action resolves, and then returns a reference to the deferred.

In this case, the callback is just going to put the data in the cache.

So, we either return the cached result, or we return an object that executes a callback when it has a value.

We get around the issue of having two drastically different return types by using {jquery}{dot}{when}.

{when} takes any number of arguments, and returns a deferred that will execute when all those arguments have data.

That data can either be a value in the argument, or if the argument is a deferred, the value of the deferred finishing execution.

We wrap that operation in some logging messages to see what happens here.

[[Switch to Result tab]]

Here we have the first call to log

And here we see the result after getting the second cached result.

Any questions on this code?

DOM Manipulation

Let's turn now to the meat of what jQuery is designed for: working with the DOM.

Selectors

jQuery works by providing a function, often namespaced as {dollar} that takes a CSS selector.

It returns an object that streamlines access to everything in your DOM matched by that selector.

Manipulation

You can then use this object to apply a variety of manipulations to the matched elements.

You can also call traversal methods on this object to move around the DOM tree.

Sizzle Engine

Full CSS3.1 Compliance

jQuery uses a custom engine to select DOM elements called Sizzle.

Sizzle provides full CSS 3.1 compliance, so anything you would do in a stylesheet you can do here.

Custom Selectors


[name!="value"]
:contains("text")
next ~ siblings
:odd, :selected

Further, there are quite a few custom selectors that Sizzle provides.

There are a variety of extensions to attribute selection, including attribute not equal, attribute has prefix, attribute contains string, and more.

The contains selector here represents a class of selectors that apply a function to the currently matched DOM nodes and culls them from the list.

Here, this requires the text inside the node has some value.

Sizzle has some hierarchical selectors

{Greater-than} is the familiar CSS child selector.

{tilde} here is the next-siblings selector; that is, every child of a node's parent that comes AFTER that node.

Beyond that are a few more custom selectors; odd here returns every other child which is good for, say, table rows, and the selected selector, which returns all selected options in a select dropdown.

There are quite a few more to use and play with, but let's look at a couple.

Selectors

http://jsfiddle.net/southerd/XpsYv/

To show how the DOM manipulation works, we need some HTML.

We'll be using this HTML for the next few examples.

This is a representation of a red-black tree in HTML, which will give us a lot of structure to work with for some of these examples.

Don't worry, we're not actually building a red-black algorithm, just using it to show off some jQuery features.

[[Click to CSS tab]]

We need a little bit of CSS, as well.

[[Click to Result tab]]

Finally, here is the rendered page. You can see the empty black leaves, the red interior nodes, and the data.

Enough background, let's get to the jQuery goodies.

Let's take a look at what some of those selectors return.

I have a couple selectors ready here.

This first selector is going to add highlights to all the leaf nodes of the tree, which in this red black tree are just placeholders.

[[Click first link]]

The selector here is a compound selector, looking for all elements with class black and the pseudoattribute of being completely empty.

[[Click clear link]]

The second selector here is going to find all nodes with data.

In our red black tree, every internal node has data of some sort.

In selectors, this means we want any red node, and every black node that is not a leaf, or, every black node that is not empty.

[[Click clear link]]

The last selector is an unfortunately complicated selector to choose sibling nodes that are both red.

This operation is important in rebalancing our tree later, but for now shows some of the more powerful selection tools.

CSS doesn't give us a way to select multiple things at the same level of a DOM tree.

Instead, we use the sibling selector to find pairs of red nodes, then use jQuery's add method to put more things in our list of matched elements.

In this case, we add a node whose previous sibling is red, and all of that node's siblings (the previous red node, in this case).

Any questions on these selectors?

Manipulation

http://jsfiddle.net/southerd/7YwdM/

Now that we've seen a bit of how selectors work, we'll go through an example of using selectors to add a node to our red black tree and rebalance the tree.

We start off by making a couple helpers.

These are jQuery plugins, that will add new behaviors to use in our jQuery selectors.

Next, we have our data to insert into the tree.

We start out by finding the node we want to insert at, this is a flattened binary find operation.

When we add a node here, we see jQuery's strength in quickly creating DOM elements- this is a conscise API, rather than dealing with Document{dot}createElement and innerHTML headaches across browsers.

For our restructure, we'll need references to the parent and grandparent.

Here we do an actual rotation-- notice again how easy jQuery makes it to move these DOM elements around the page.

Finally, for the red-black insertion we need to recolor. Those operations are very easy with our plugins we defined above, and they pay off big time in a full implementation.

Let's see what happens when we run this. [[Switch to results tab]]

[[Press insert button]]

Here's our new data.

Let's go through this again, this time stopping to look at each step.

Manipulation

http://jsfiddle.net/southerd/WrWmS/

We've got our tree here

[[Click find link]] Here's the node we're inserting at.

[[Press insert button]]

And there it is, but now we have a double-red.

We'll need to fix that, so let's grab the parent and grandparent.

[[Click ancestors link]]

We'll go ahead and rotate the tree.

[[Click rotate link]]

We've lost a couple nodes...

[[Click append link]]

But because jQuery had a reference to them, they just got detached from the DOM and added back in here.

Let's clean up from our example highlighting

[[Click rekey link]]

And finally recolor everything so it's correct.

[[Click recolor link]]

And there we go, we had about a dozen things to do for this operation, and jQuery let us do that without much if any spurious boilerplate code.

Any questions?

Plugins, UI, Projects

Now that we've covered some of the more expressive features of jQuery, I'd like to take some time to talk about the 3rd party ecosystem around jQuery.

There's just too much here to do code examples for all of this, so instead I'm going to talk about what is available and include links for you to follow up with later, as needed.

Let's take a look at some of this.

jQuery provides a very powerful mechanism for extending the base functionality, and this has let a vast number of people write plugins for jQuery.

There is a project separate from jQuery core called jQuery UI, which provides a handful of very useful interface utilities and a few interface components, as well as a powerful theming library.

Finally, I'll close with a discussion of how to start using jQuery in your projects today.

Plugins

As I mentioned, there is a tremendous ecosystem of jQuery plugins and developers.

This is both a boon and a curse.

Diverse 3rd party ecosystem

Often, there are already excellent 3rd party libraries that will solve some of the common problems you'll face.

That said, there is also a lot of terrible code that gets put out because someone else wanted to write the same thing differently.

There are a few plugins I'd like to highlight, since they do cover tasks that nearly every web application needs, and I also have some guidelines for finding other plugins.

Excellent Plugins

The most versatile extension to jQuery for handling data is the Datatables plugin. It provides numerous table features, including paging, column sorting, and really nearly any tabular data constraint you might need.

When dealing with user input, HTML forms can require significant validation.

The jQuery validation plugin handles an absurd variety of validation cases, and in basic usage is almost trivial to add to a page.

JMTT is the jQuery Minimal Tree-Table, a plugin designed to add combined tree and table functionality to websites.

It is implemented as a jQuery Widget, and uses the eventing model as its primary API.

These are some of the better plugins I've come across and continue to use in jQuery.

Terrible plugins

When I need to evaluate plugins for some other feature, I usually spend about 10 minutes googling to see what others have found.

If I do find something, I take about 20 minutes to read through their documentation and source code, to get a feel for whether it will be worth trying to use that plugin.

Once I've spent that much time with a plugin, It's pretty easy to decide if it will save time, or if the feature should be implemented fresh.

jQuery UI

Aside jQuery core is a project called jQuery UI.

jQuery UI is more of a toolkit, in that it provides a variety of abstract base features, and components that interoperate well with one another.

UI Helpers

At its base level, jQuery UI has a variety of helper classes that streamline many issues in HTML and CSS layouts.

The Position class provides a myriad of ways to position DOM elements around eachother.

The draggable and droppable helpers provide a wealth of Dragn & Drop features for new widgets to grab on to.

Resizable, selectable, and sortable are just some of the other helpers UI exposes.

UI Components

The components are smaller in scope than some Dojo or Ext components.

These are all meant to be used as pieces in an HTML page, rather than full layout managers like in Ext or Dojo.

I've highlighted here some demos that show off some of the features of jQuery UI.

Themes

So far, jQuery UI is a little lackluster compared to its competitors.

That's where jQuery UI themes and Themeroller comes in.

While Ext and Dojo have some theming capabilities, the consistency jQuery UI has in its Themeroller framework continually impress me over the other libraries.

In Your Project

One of the questions I've gotten a couple times while preparing this presentation is how can we start using jQuery today.

Small

First, jQuery is very small- the current production release is 31 K, smaller than a jpeg image.

You can include it with a project at no significant cost to network latency, page size, or much else.

Efficient

jQuery is very efficient.

It's got some really smart people doing a lot of work to make sure jQuery does what it does as fast as possible

Interoperable

jQuery plays very well with other libraries, and plays very well across browsers.

Whether used piecemeal to augment other libraries, or as an extension on Dojo or Ext layouts, jQuery can make some simple tasks trivial to do.

jQuery also takes the headache out from working across browsers.

While different browsers may have implemented some features slightly differently (say, HTML5 datasets), jQuery makes them all just work the same way.

Make Plugins

Once you get started using jQuery to add features here and there, you'll see things in a project you need over and over.

Learning the jQuery plugin architecture will vault your Javascript development to the next level.

To make plugins right requires you to embrace the MVC semantics of DOM, CSS, and javascript, but once you get that paradigm, your sites can really start to pop.

Write Less, Do More

I know we've covered a lot in a very short amount of time.

I presented this not in the hopes of making you all jQuery experts today, but rather to highlight what jQuery excels at, and perhaps dispel some myths about this tool.

At very least, I hope you will recognize there is a very powerful tool available for use in your javascript toolkit, and maybe you'll start talking about it on your projects.

Thanks

Drew Tayman, Justin Grant

jQuery, jQuery UI

impress.js (Bartek Szopka @bartaz)

[[Click through]]

Bibliography

jQuery Documentation - http://docs.jquery.com/Main_Page

jQuery Novice to Ninja - http://www.sitepoint.com/books/jquery1/

Hacking at 0301: Understanding jQuery UI widgets - http://bililite.nfshost.com/blog/understanding-jquery-ui-widgets-a-tutorial/

[[Click through]]

If you have any questions, feel free to email or IM me.

Thank you for your time :)

Are there any final questions?

Use spacebar, arrow keys, or click to navigate. Press 'n' for speaker notes.