# jQuery Fundamentals

### With contributions by James Padolsey, Paul Irish, and others. See the GitHub repository for a complete history of contributions.

Licensed by Rebecca Murphey under the Creative
. You
are free to copy, distribute, transmit, and remix this work, provided
you attribute the work to Rebecca Murphey as the original author and
reference the GitHub
repository for the work
. If you alter, transform, or build upon
this work, you may distribute the resulting work only under the same,
similar or a compatible license. Any of the above conditions can be
waived if you get permission from the copyright holder. For any reuse or
distribution, you must make clear to others the license terms of this
work. The best way to do this is with a link to
.

# Part I. JavaScript 101

## Syntax Basics

Understanding statements, variable naming, whitespace, and other
basic JavaScript syntax.

Example 2.1. A simple variable declaration

`var foo = 'hello world';`

Example 2.3. Parentheses indicate precedence

```2 * 3 + 5;    // returns 11; multiplication happens first
2 * (3 + 5);  // returns 16; addition happens first```

Example 2.4. Tabs enhance readability, but have no special meaning

```var foo = function() {
console.log('hello');
};```

## Operators

### Basic Operators

Basic operators allow you to manipulate values.

Example 2.5. Concatenation

```var foo = 'hello';
var bar = 'world';

console.log(foo + ' ' + bar); // 'hello world'```

Example 2.6. Multiplication and division

```2 * 3;
2 / 3;```

Example 2.7. Incrementing and decrementing

```var i = 1;

var j = ++i;  // pre-increment:  j equals 2; i equals 2
var k = i++;  // post-increment: k equals 2; i equals 3```

### Logical Operators

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

Example 2.11. Logical AND and OR operators

```var foo = 1;
var bar = 0;
var baz = 2;

foo || bar;   // returns 1, which is true
bar || foo;   // returns 1, which is true

foo && bar;   // returns 0, which is false
foo && baz;   // returns 2, which is true
baz && foo;   // returns 1, which is true```

Though it may not be clear from the example, the `||`
operator returns the value of the first truthy operand, or, in cases
where neither operand is truthy, it’ll return the last of both operands.
The `&&` operator returns the value of the first
false operand, or the value of the last operand if both operands are
truthy.

Be sure to consult the section called “Truthy and Falsy Things” for more details on
which values evaluate to `true` and which evaluate to
`false`.

### Note

You’ll sometimes see developers use these logical operators for
flow control instead of using `if` statements. For
example:

```// do something with foo if foo is truthy
foo && doSomething(foo);

// set bar to baz if baz is truthy;
// otherwise, set it to the return
// value of createBar()
var bar = baz || createBar();```

This style is quite elegant and pleasantly terse; that said, it
can be really hard to read, especially for beginners. I bring it up
here so you’ll recognize it in code you read, but I don’t recommend
using it until you’re extremely comfortable with what it means and how
you can expect it to behave.

### Comparison Operators

Comparison operators allow you to test whether values are
equivalent or whether values are identical.

Example 2.12. Comparison operators

```var foo = 1;
var bar = 0;
var baz = '1';
var bim = 2;

foo == bar;   // returns false
foo != bar;   // returns true
foo == baz;   // returns true; careful!

foo === baz;             // returns false
foo !== baz;             // returns true
foo === parseInt(baz);   // returns true

foo > bim;    // returns false
bim > baz;    // returns true
foo <= baz;   // returns true```

## Conditional Code

Sometimes you only want to run a block of code under certain
conditions. Flow control — via `if` and `else`
blocks — lets you run code only under certain conditions.

Example 2.13. Flow control

```var foo = true;
var bar = false;

if (bar) {
// this code will never run
console.log('hello!');
}

if (bar) {
// this code won't run
} else {
if (foo) {
// this code will run
} else {
// this code would run if foo and bar were both false
}
}```

Be mindful not to define functions with the same name multiple times
within separate `if`/`else` blocks, as doing so may
not have the expected result.

### Truthy and Falsy Things

In order to use flow control successfully, it’s important to
understand which kinds of values are “truthy” and which kinds of values
are “falsy.” Sometimes, values that seem like they should evaluate one
way actually evaluate another.

Example 2.14. Values that evaluate to `true`

```'0';
'any string';
[];  // an empty array
{};  // an empty object
1;   // any non-zero number```

Example 2.15. Values that evaluate to `false`

```0;
'';  // an empty string
NaN; // JavaScript's "not-a-number" variable
null;
undefined;  // be careful -- undefined can be redefined!```

### Switch Statements

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

Example 2.17. A switch statement

```switch (foo) {

case 'bar':
alert('the value was bar -- yay!');
break;

case 'baz':
break;

default:
break;

}```

Switch statements have somewhat fallen out of favor in JavaScript,
because often the same behavior can be accomplished by creating an object
that has more potential for reuse, testing, etc. For example:

```var stuffToDo = {
'bar' : function() {
alert('the value was bar -- yay!');
},

'baz' : function() {
},

'default' : function() {
}
};

if (stuffToDo[foo]) {
stuffToDo[foo]();
} else {
stuffToDo['default']();
}```

We’ll look at objects in greater depth later in this
chapter.

## Loops

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

Example 2.18. Loops

```// logs 'try 0', 'try 1', ..., 'try 4'
for (var i=0; i<5; i++) {
console.log('try ' + i);
}```

Note that in
Example 2.18, “Loops” even though we use the
keyword var before the variable name `i`,
this does not “scope” the variable `i` to the loop block.
We’ll discuss scope in depth later in this chapter.

### Breaking and continuing

Usually, a loop’s termination will result from the conditional
statement not evaluating to true, but it is possible to stop a loop in
its tracks from within the loop’s body with the `break`
statement.

Example 2.23. Stopping a loop

```for (var i = 0; i < 10; i++) {
if (something) {
break;
}
}```

You may also want to continue the loop without executing more of
the loop’s body. This is done using the `continue`
statement.

Example 2.24. Skipping to the next iteration of a loop

```for (var i = 0; i < 10; i++) {

if (something) {
continue;
}

// The following statement will only be executed
// if the conditional 'something' has not been met
console.log('I have been reached');

}```

## Reserved Words

JavaScript has a number of “reserved words,” or words that have
special meaning in the language. You should avoid using these words in
your code except when using them with their intended meaning.

• `break`

• `case`

• `catch`

• `continue`

• `default`

• `delete`

• `do`

• `else`

• `finally`

• `for`

• `function`

• `if`

• `in`

• `instanceof`

• `new`

• `return`

• `switch`

• `this`

• `throw`

• `try`

• `typeof`

• `var`

• `void`

• `while`

• `with`

• `abstract`

• `boolean`

• `byte`

• `char`

• `class`

• `const`

• `debugger`

• `double`

• `enum`

• `export`

• `extends`

• `final`

• `float`

• `goto`

• `implements`

• `import`

• `int`

• `interface`

• `long`

• `native`

• `package`

• `private`

• `protected`

• `public`

• `short`

• `static`

• `super`

• `synchronized`

• `throws`

• `transient`

• `volatile`

## Arrays

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

Example 2.25. A simple array

`var myArray = [ 'hello', 'world' ];`

Example 2.26. Accessing array items by index

```var myArray = [ 'hello', 'world', 'foo', 'bar' ];
console.log(myArray[3]);   // logs 'bar'```

Example 2.27. Testing the size of an array

```var myArray = [ 'hello', 'world' ];
console.log(myArray.length);   // logs 2```

Example 2.28. Changing the value of an array item

```var myArray = [ 'hello', 'world' ];
myArray[1] = 'changed';```

Example 2.29. Adding elements to an array

```var myArray = [ 'hello', 'world' ];
myArray.push('new');```

Example 2.30. Working with arrays

```var myArray = [ 'h', 'e', 'l', 'l', 'o' ];
var myString = myArray.join('');   // 'hello'
var mySplit = myString.split('');  // [ 'h', 'e', 'l', 'l', 'o' ]```

## Functions

Functions contain blocks of code that need to be executed
repeatedly. Functions can take zero or more arguments, and can optionally
return a value.

Functions can be created in a variety of ways:

Example 2.32. Function Declaration

`function foo() { /* do something */ }`

Example 2.33. Named Function Expression

`var foo = function() { /* do something */ }`

I prefer the named function expression method of setting a
function’s name, for some rather
in-depth
and technical reasons
. You are likely to see both methods used in
others’ JavaScript code.

### Using Functions

Example 2.34. A simple function

```var greet = function(person, greeting) {
var text = greeting + ', ' + person;
console.log(text);
};

greet('Rebecca', 'Hello');```

Example 2.35. A function that returns a value

```var greet = function(person, greeting) {
var text = greeting + ', ' + person;
return text;
};

console.log(greet('Rebecca','hello'));```

Example 2.36. A function that returns another function

```var greet = function(person, greeting) {
var text = greeting + ', ' + person;
return function() { console.log(text); };
};

var greeting = greet('Rebecca', 'Hello');
greeting();```

### Functions as Arguments

In JavaScript, functions are “first-class citizens” — they can be
assigned to variables or passed to other functions as arguments. Passing
functions as arguments is an extremely common idiom in jQuery.

Example 2.38. Passing an anonymous function as an argument

```var myFn = function(fn) {
var result = fn();
console.log(result);
};

myFn(function() { return 'hello world'; });   // logs 'hello world'```

Example 2.39. Passing a named function as an argument

```var myFn = function(fn) {
var result = fn();
console.log(result);
};

var myOtherFn = function() {
return 'hello world';
};

myFn(myOtherFn);   // logs 'hello world'```

## Testing Type

JavaScript offers a way to test the “type” of a variable. However,
the result can be confusing — for example, the type of an Array is
“object”.

It’s common practice to use the `typeof` operator when
trying to determining the type of a specific value.

Example 2.40. Testing the type of various variables

```var myFunction = function() {
console.log('hello');
};

var myObject = {
foo : 'bar'
};

var myArray = [ 'a', 'b', 'c' ];

var myString = 'hello';

var myNumber = 3;

typeof myFunction;   // returns 'function'
typeof myObject;     // returns 'object'
typeof myArray;      // returns 'object' -- careful!
typeof myString;     // returns 'string';
typeof myNumber;     // returns 'number'

typeof null;         // returns 'object' -- careful!

if (myArray.push && myArray.slice && myArray.join) {
// probably an array
// (this is called "duck typing")
}

if (Object.prototype.toString.call(myArray) === '[object Array]') {
// Definitely an array!
// This is widely considered as the most rebust way
// to determine if a specific value is an Array.
}```

jQuery offers utility methods to help you determine the type of an
arbitrary value. These will be covered later.

## Scope

“Scope” refers to the variables that are available to a piece of
code at a given time. A lack of understanding of scope can lead to
frustrating debugging experiences.

When a variable is declared inside of a function using the
`var` keyword, it is only available to code inside of that
function — code outside of that function cannot access the variable. On
the other hand, functions defined inside that
variable.

Furthermore, variables that are declared inside a function without
the `var` keyword are not local to the function — JavaScript
will traverse the scope chain all the way up to the window scope to find
where the variable was previously defined. If the variable wasn’t
previously defined, it will be defined in the global scope, which can have
extremely unexpected consequences;

scope

```var foo = 'hello';

var sayHello = function() {
console.log(foo);
};

sayHello();         // logs 'hello'
console.log(foo);   // also logs 'hello'```

Example 2.42. Code outside the scope in which a variable was defined does not

```var sayHello = function() {
var foo = 'hello';
console.log(foo);
};

sayHello();         // logs 'hello'
console.log(foo);   // doesn't log anything```

Example 2.43. Variables with the same name can exist in different scopes with
different values

```var foo = 'world';

var sayHello = function() {
var foo = 'hello';
console.log(foo);
};

sayHello();         // logs 'hello'
console.log(foo);   // logs 'world'```

Example 2.44. Functions can “see” changes in variable values after the function
is defined

```var myFunction = function() {
var foo = 'hello';

var myFn = function() {
console.log(foo);
};

foo = 'world';

return myFn;
};

var f = myFunction();
f();  // logs 'world' -- uh oh```

Example 2.45. Scope insanity

```// a self-executing anonymous function
(function() {
var baz = 1;
var bim = function() { alert(baz); };
bar = function() { alert(baz); };
})();

console.log(baz);  // baz is not defined outside of the function

bar();  // bar is defined outside of the anonymous function
// because it wasn't declared with var; furthermore,
// because it was defined in the same scope as baz,
// outside of the function does not

bim();  // bim is not defined outside of the anonymous function,
// so this will result in an error```

## Closures

Closures are an extension of the concept of scope — functions have
access to variables that were available in the scope where the function
was created. If that’s confusing, don’t worry: closures are generally best
understood by example.

In Example 2.44, “Functions can “see” changes in variable values after the function
is defined”

we saw how functions have access to changing variable values. The same
sort of behavior exists with functions defined within loops — the
function “sees” the change in the variable’s value even after the function
is defined, resulting in all clicks alerting 5.

Example 2.46. How to lock in the value of `i`?

```/* this won't behave as we want it to; */
/* every click will alert 5 */
for (var i=0; i<5; i++) {
\$('<p>click me</p>').appendTo('body').click(function() {
});
}```

Example 2.47. Locking in the value of `i` with a closure

```/* fix: “close” the value of i inside createFunction, so it won't change */
var createFunction = function(i) {
};

for (var i=0; i<5; i++) {
\$('<p>click me</p>').appendTo('body').click(createFunction(i));
}```

# Part II. jQuery: Basic Concepts

## Selecting Elements

Following are a few examples of common selection techniques.

Example 3.4. Selecting elements by ID

`\$('#myId'); // note IDs must be unique per page`

Example 3.5. Selecting elements by class name

`\$('div.myClass'); // performance improves if you specify element type`

Example 3.6. Selecting elements by attribute

`\$('input[name=first_name]'); // beware, this can be very slow`

Example 3.7. Selecting elements by compound CSS selector

`\$('#contents ul.people li');`

Example 3.8. Pseudo-selectors

```\$('a.external:first');
\$('tr:odd');
\$('#myForm :input');   // select all input-like elements in a form
\$('div:visible');
\$('div:gt(2)');        // all except the first three divs
\$('div:animated');     // all currently animated divs```

### Note

When you use the `:visible` and `:hidden`
pseudo-selectors, jQuery tests the actual visibility of the element, not
its CSS visibility or display — that is, it looks to see if the
element’s physical height and width on the page are
both greater than zero. However, this test doesn’t work with
`<tr>` elements; in this case, jQuery does check the
CSS `display` property, and considers an element hidden if
its `display` property is set to `none`. Elements
that have not been added to the DOM will always be considered hidden,
even if the CSS that would affect them would render them visible. (See
the Manipulation section later in this chapter to learn how to create
and add elements to the DOM.)

For reference, here is the code jQuery uses to determine whether

```jQuery.expr.filters.hidden = function( elem ) {
var width = elem.offsetWidth, height = elem.offsetHeight,
skip = elem.nodeName.toLowerCase() === "tr";

// does the element have 0 height, 0 width,
// and it's not a <tr>?
return width === 0 && height === 0 && !skip ?

// then it must be hidden
true :

// but if it has width and height
// and it's not a <tr>
width > 0 && height > 0 && !skip ?

// then it must be visible
false :

// if we get here, the element has width
// and height, but it's also a <tr>,
// so check its display property to
// decide whether it's hidden
jQuery.curCSS(elem, "display") === "none";
};

jQuery.expr.filters.visible = function( elem ) {
return !jQuery.expr.filters.hidden( elem );
};```

### Saving Selections

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

Example 3.10. Storing selections in a variable

`var \$divs = \$('div');`

### Note

In Example 3.10, “Storing selections in a variable”,
the variable name begins with a dollar sign. Unlike in other
– it’s just another character. We use it here to indicate that the
variable contains a jQuery object. This practice — a sort of Hungarian
notation
— is merely convention, and is not mandatory.

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

### Note

A selection only fetches the elements that are on the page when
you make the selection. If you add elements to the page later, you’ll
have to repeat the selection or otherwise add them to the selection
stored in the variable. Stored selections don’t magically update when
the DOM changes.

### Refining & Filtering Selections

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

Example 3.11. Refining selections

```\$('div.foo').has('p');          // div.foo elements that contain <p>'s
\$('h1').not('.bar');            // h1 elements that don't have a class of bar
\$('ul li').filter('.current');  // unordered list items with class of current
\$('ul li').first();             // just the first unordered list item
\$('ul li').eq(5);               // the sixth ```

## CSS, Styling, & Dimensions

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

Example 3.18. Getting CSS properties

`\$('h1').css('fontSize'); // returns a string such as "19px"`

Example 3.19. Setting CSS properties

```\$('h1').css('fontSize', '100px'); // setting an individual property
\$('h1').css({ 'fontSize' : '100px', 'color' : 'red' }); // setting multiple properties```

Note the style of the argument we use on the second line — it is
an object that contains multiple properties. This is a common way to pass
multiple arguments to a function, and many jQuery setter methods accept
objects to set mulitple values at once.

### Dimensions

jQuery offers a variety of methods for obtaining and modifying
dimension and position information about an element.

The code in Example 3.21, “Basic dimensions methods”
is just a very brief overview of the dimensions functionality in jQuery;
for complete details about jQuery dimension methods, visit http://api.jquery.com/category/dimensions/.

Example 3.21. Basic dimensions methods

```\$('h1').width('50px');   // sets the width of all H1 elements
\$('h1').width();         // gets the width of the first H1

\$('h1').height('50px');  // sets the height of all H1 elements
\$('h1').height();        // gets the height of the first H1

\$('h1').position();      // returns an object containing position
// information for the first H1 relative to
// its "offset (positioned) parent"```

## Traversing

Once you have a jQuery selection, you can find other elements using
your selection as a starting point.

### Note

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

Example 3.24. Moving around the DOM using traversal methods

```\$('h1').next('p');
\$('div:visible').parent();
\$('input[name=first_name]').closest('form');
\$('#myList').children();
\$('li.selected').siblings();```

You can also iterate over a selection using `\$.fn.each`.
This method iterates over all of the elements in a selection, and runs a
function for each one. The function receives the index of the current
element and the DOM element itself as arguments. Inside the function, the
DOM element is also available as `this` by default.

Example 3.25. Iterating over a selection

```\$('#myList li').each(function(idx, el) {
console.log(
'Element ' + idx +
'has the following html: ' +
\$(el).html()
);
});```

## Manipulating Elements

Once you’ve made a selection, the fun begins. You can change, move,
remove, and clone elements. You can also create new elements via a simple
syntax.

### Creating New Elements

jQuery offers a trivial and elegant way to create new elements
using the same `\$()` method you use to make
selections.

Example 3.29. Creating new elements

```\$('<p>This is a new paragraph</p>');
\$('<li class="new">new list item</li>');```

Example 3.30. Creating a new element with an attribute object

```\$('<a/>', {
html : 'This is a <strong>new</strong> link',
'class' : 'new',
href : 'foo.html'
});```

Note that in the attributes object we included as the second
argument, the property name class is quoted, while the property names
text and href are not. Property names generally do not need to be quoted
unless they are reserved words (as class is in this case).

When you create a new element, it is not immediately added to the
page. There are several ways to add an element to the page once it’s
been created.

Example 3.31. Getting a new element on to the page

```var \$myNewElement = \$('<p>New element</p>');
\$myNewElement.appendTo('#content');

\$myNewElement.insertAfter('ul:last'); // this will remove the p from #content!
\$('ul').last().after(\$myNewElement.clone());  // clone the p so now we have 2```

Strictly speaking, you don’t have to store the created element
in a variable — you could just call the method to add the element to
the page directly after the \$(). However, most of the time you will want
a reference to the element you added, so you don’t need to select it
later.

You can even create an element as you’re adding it to the page,
but note that in this case you don’t get a reference to the newly
created element.

### Manipulating Attributes

jQuery’s attribute manipulation capabilities are extensive. Basic
changes are simple, but the \$.fn.attr method also allows for more
complex manipulations.

Example 3.33. Manipulating a single attribute

`\$('#myDiv a:first').attr('href', 'newDestination.html');`

Example 3.34. Manipulating multiple attributes

```\$('#myDiv a:first').attr({
href : 'newDestination.html',
rel : 'super-special'
});```

Example 3.35. Using a function to determine an attribute’s new value

```\$('#myDiv a:first').attr({
rel : 'super-special',
href : function() {
return '/new/' + \$(this).attr('href');
}
});

\$('#myDiv a:first').attr('href', function() {
return '/new/' + \$(this).attr('href');
});```

## Utility Methods

\$.trim

```\$.trim('    lots of extra whitespace    ');
// returns 'lots of extra whitespace'```
\$.each
Iterates over arrays and objects.

```\$.each([ 'foo', 'bar', 'baz' ], function(idx, val) {
console.log('element ' + idx + 'is ' + val);
});

\$.each({ foo : 'bar', baz : 'bim' }, function(k, v) {
console.log(k + ' : ' + v);
});```

### Note

There is also a method `\$.fn.each`, which is used
for iterating over a selection of elements.

\$.inArray
Returns a value’s index in an array, or -1 if the value is not
in the array.

```var myArray = [ 1, 2, 3, 5 ];

if (\$.inArray(4, myArray) !== -1) {
console.log('found it!');
}```
\$.extend
Changes the properties of the first object using the
properties of subsequent objects.

```var firstObject = { foo : 'bar', a : 'b' };
var secondObject = { foo : 'baz' };

var newObject = \$.extend(firstObject, secondObject);
console.log(firstObject.foo); // 'baz'
console.log(newObject.foo);   // 'baz'```

If you don’t want to change any of the objects you pass to
`\$.extend`, pass an empty object as the first
argument.

```var firstObject = { foo : 'bar', a : 'b' };
var secondObject = { foo : 'baz' };

var newObject = \$.extend({}, firstObject, secondObject);
console.log(firstObject.foo); // 'bar'
console.log(newObject.foo);   // 'baz'```
\$.proxy
Returns a function that will always run in the provided scope
— that is, sets the meaning of `this` inside the passed
function to the second argument.

```var myFunction = function() { console.log(this); };
var myObject = { foo : 'bar' };

myFunction(); // logs window object

var myProxyFunction = \$.proxy(myFunction, myObject);
myProxyFunction(); // logs myObject object```

If you have an object with methods, you can pass the object
and the name of a method to return a function that will always run
in the scope of the object.

```var myObject = {
myFn : function() {
console.log(this);
}
};

\$('#foo').click(myObject.myFn); // logs DOM element #foo
\$('#foo').click(\$.proxy(myObject, 'myFn')); // logs myObject```

## Checking types

As mentioned in the “JavaScript basics” section, jQuery offers
a few basic utility methods for determining the type of a specific
value.

Example 4.1. Checking the type of an arbitrary value

```var myValue = [1, 2, 3];

// Using JavaScript's typeof operator to test for primative types
typeof myValue == 'string'; // false
typeof myValue == 'number'; // false
typeof myValue == 'undefined'; // false
typeof myValue == 'boolean'; // false

// Using strict equality operator to check for null
myValue === null; // false

// Using jQuery's methods to check for non-primative types
jQuery.isFunction(myValue); // false
jQuery.isPlainObject(myValue); // false
jQuery.isArray(myValue); // true```

## Data Methods

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

Example 4.2. Storing and retrieving data related to an element

```\$('#myDiv').data('keyName', { foo : 'bar' });
\$('#myDiv').data('keyName'); // { foo : 'bar' }```

You can store any kind of data on an element, and it’s hard to
overstate the importance of this when you get into complex application
development. For the purposes of this class, we’ll mostly use
`\$.fn.data` to store references to other elements.

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

Example 4.3. Storing a relationship between elements using
`\$.fn.data`

```\$('#myList li').each(function() {
var \$li = \$(this), \$div = \$li.find('div.content');
\$li.data('contentDiv', \$div);
});

// later, we don't have to find the div again;
// we can just read it from the list item's data
var \$firstLi = \$('#myList li:first');
\$firstLi.data('contentDiv').html('new content');```

In addition to passing `\$.fn.data` a single key-value
pair to store data, you can also pass an object containing one or more
pairs.

## Feature & Browser Detection

Although jQuery eliminates most JavaScript browser quirks, there are
environment.

The `\$.support` object is dedicated to determining what
features a browser supports; it is recommended as a more “future-proof”
method of customizing your JavaScript for different browser
environments.

The `\$.browser` object was deprecated in favor of the
`\$.support` object, but it will not be removed from jQuery
anytime soon. It provides direct detection of the browser brand and
version.

## Overview

jQuery provides simple methods for attaching event handlers to
selections. When an event occurs, the provided function is executed.
Inside the function, this refers to the element that was clicked.

The event handling function can receive an event object. This object
can be used to determine the nature of the event, and to prevent the
event’s default behavior.

For details on the event object, visit http://api.jquery.com/category/events/event-object/.

## Connecting Events to Elements

jQuery offers convenience methods for most common events, and these
are the methods you will see used most often. These methods — including
`\$.fn.click`, `\$.fn.focus`, `\$.fn.blur`,
`\$.fn.change`, etc. — are shorthand for jQuery’s
`\$.fn.bind` method. The bind method is useful for binding the
same hadler function to multiple events, and is also used when you want to
provide data to the event hander, or when you are working with custom
events.

Example 5.1. Event binding using a convenience method

```\$('p').click(function() {
console.log('click');
});```

Example 5.2. Event biding using the `\$.fn.bind` method

```\$('p').bind('click', function() {
console.log('click');
});```

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

```\$('input').bind(
'click change',  // bind to multiple events
{ foo : 'bar' }, // pass in data

function(eventObject) {
console.log(eventObject.type, eventObject.data);
// logs event type, then { foo : 'bar' }
}
);```

### Disconnecting Events

To disconnect an event handler, you use the
`\$.fn.unbind` method and pass in the event type to unbind. If
you attached a named function to the event, then you can isolate the
unbinding to that named function by passing it as the second
argument.

Example 5.6. Unbinding a particular click handler

```var foo = function() { console.log('foo'); };
var bar = function() { console.log('bar'); };

\$('p').bind('click', foo).bind('click', bar);
\$('p').unbind('click', bar); // foo is still bound to the click event```

### Namespacing Events

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

Example 5.7. Namespacing events

```\$('p').bind('click.myNamespace', function() { /* ... */ });
\$('p').unbind('click.myNamespace');
\$('p').unbind('.myNamespace'); // unbind all events in the namespace```

## Increasing Performance with Event Delegation

You’ll frequently use jQuery to add new elements to the page, and
when you do, you may need to bind events to those new elements — events
you already bound to similar elements that were on the page originally.
page, you can use event delegation. With event delegation, you bind your
event to a container element, and then when the event occurs, you look to
see which contained element it occurred on. If this sounds complicated,
luckily jQuery makes it easy with its `\$.fn.live` and
`\$.fn.delegate` methods.

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

Example 5.10. Event delegation using `\$.fn.delegate`

```\$('#myUnorderedList').delegate('li', 'click', function(e) {
var \$myListItem = \$(this);
// ...
});```

Example 5.11. Event delegation using `\$.fn.live`

```\$('#myUnorderedList li').live('click', function(e) {
var \$myListItem = \$(this);
// ...
});```

## Built-in Effects

Frequently used effects are built into jQuery as methods:

## Custom Effects with `\$.fn.animate`

jQuery makes it possible to animate arbitrary CSS properties via the
`\$.fn.animate` method. The `\$.fn.animate` method
lets you animate to a set value, or to a value relative to the current
value.

Example 6.6. Custom effects with `\$.fn.animate`

```\$('div.funtimes').animate(
{
left : "+=50",
opacity : 0.25
},
300, // duration
function() { console.log('done!'); // calback
});```

### Easing

As of jQuery 1.4, it is possible to do per-property easing when
using the \$.fn.animate method.

Example 6.7. Per-property easing

```\$('div.funtimes').animate(
{
left : [ "+=50", "swing" ],
opacity : [ 0.25, "linear" ]
},
300
);```

## Key Concepts

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

### Data Types

jQuery generally requires some instruction as to the type of data
you expect to get back from an Ajax request; in some cases the data type
is specified by the method name, and in other cases it is provided as
part of a configuration object. There are several options:

text
For transporting simple strings

html
For transporting blocks of HTML to be placed on the
page

script
For adding a new script to the page

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

### Note

As of jQuery 1.4, if the JSON data sent by your server
isn’t properly formatted, the request may fail silently. See
http://json.org for
details on properly formatting JSON, but as a general rule,
use built-in language methods for generating JSON on the
server to avoid syntax issues.

jsonp
For transporting JSON data from another domain

xml
For transporting data in a custom XML schema

I am a strong proponent of using the JSON format in most cases,
as it provides the most flexibility. It is especially useful for sending
both HTML and data at the same time.

## jQuery’s Ajax-Related Methods

While jQuery does offer many Ajax-related convenience methods, the
core `\$.ajax` method is at the heart of all of them, and
understanding it is imperative. We’ll review it first, and then touch
briefly on the convenience methods.

I generally use the \$.ajax method and do not use convenience
methods. As you’ll see, it offers features that the convenience methods do
not, and its syntax is more easily understandable, in my opinion.

### \$.ajax

Example 7.1. Using the core \$.ajax method

```\$.ajax({
// the URL for the request
url : 'post.php',

// the data to send
// (will be converted to a query string)
data : { id : 123 },

// whether this is a POST or GET request
type : 'GET',

// the type of data we expect back
dataType : 'json',

// code to run if the request succeeds;
// the response is passed to the function
success : function(json) {
\$('<h1/>').text(json.title).appendTo('body');
\$('<div class="content"/>')
.html(json.html).appendTo('body');
},

// code to run if the request fails;
// the raw request and status codes are
// passed to the function
error : function(xhr, status) {
},

// code to run regardless of success or failure
complete : function(xhr, status) {
}
});```

#### `\$.ajax` Options

There are many, many options for the \$.ajax method, which is
part of its power. For a complete list of options, visit
http://api.jquery.com/jQuery.ajax/;
here are several that you will use frequently:

async
Set to `false` if the request should be sent
synchronously. Defaults to `true`. Note that if you
set this option to false, your request will block execution of
other code until the response is received.

cache
Whether to use a cached response if available. Defaults to
`true` for all dataTypes except “script” and “jsonp”.
When set to false, the URL will simply have a cachebusting
parameter appended to it.

complete
A callback function to run when the request is complete,
regardless of success or failure. The function receives the raw
request object and the text status of the request.

context
The scope in which the callback function(s) should run
(i.e. what `this` will mean inside the callback
function(s)). By default, `this` inside the callback
function(s) refers to the object originally passed to
`\$.ajax`.

data
The data to be sent to the server. This can either be an
object or a query string, such as
`foo=bar&baz=bim`.

dataType
The type of data you expect back from the server. By
default, jQuery will look at the MIME type of the response if no
dataType is specified.

error
A callback function to run if the request results in an
error. The function receives the raw request object and the text
status of the request.

jsonp
The callback name to send in a query string when making a
JSONP request. Defaults to “callback”.

success
A callback function to run if the request succeeds. The
function receives the response data (converted to a JavaScript
object if the dataType was JSON), as well as the text status of
the request and the raw request object.

timeout
The time in milliseconds to wait before considering the
request a failure.

Set to true to use the param serialization style in use
prior to jQuery 1.4. For details, see http://api.jquery.com/jQuery.param/.

type
The type of the request, “POST” or “GET”. Defaults to
“GET”. Other request types, such as “PUT” and “DELETE” can be
used, but they may not be supported by all browsers.

url
The URL for the request.

The `url` option is the only required property of the
`\$.ajax` configuration object; all other properties are
optional.

### Convenience Methods

If you don’t need the extensive configurability of
`\$.ajax`, and you don’t care about handling errors, the Ajax
convenience functions provided by jQuery can be useful, terse ways to
accomplish Ajax requests. These methods are just “wrappers” around the
core `\$.ajax` method, and simply pre-set some of the options
on the `\$.ajax` method.

The convenience methods provided by jQuery are:

In each case, the methods take the following arguments, in
order:

Example 7.2. Using jQuery’s Ajax convenience methods

```// get plain text or html
\$.get('/users.php', { userId : 1234 }, function(resp) {
console.log(resp);
});

// add a script to the page, then run a function defined in it
\$.getScript('/static/js/myScript.js', function() {
functionFromMyScript();
});

// get JSON-formatted data from the server
\$.getJSON('/details.php', function(resp) {
\$.each(resp, function(k, v) {
console.log(k + ' : ' + v);
});
});```

## Ajax and Forms

jQuery’s ajax capabilities can be especially useful when dealing
with forms. The
jQuery
Form Plugin
is a well-tested tool for adding Ajax capabilities to
forms, and you should generally use it for handling forms with Ajax rather
than trying to roll your own solution for anything remotely complex. That
said, there are a two jQuery methods you should know that relate to form
processing in jQuery: `\$.fn.serialize` and
`\$.fn.serializeArray`.

Example 7.5. Turning form data into a query string

`\$('#myForm').serialize();`

Example 7.6. Creating an array of objects containing form data

```\$('#myForm').serializeArray();

// creates a structure like this:
[
{ name : 'field1', value : 123 },
{ name : 'field2', value : 'hello world' }
]```

## Working with JSONP

Example 7.7. Using YQL and JSONP

```\$.ajax({
url : 'http://query.yahooapis.com/v1/public/yql',

// the name of the callback parameter,
// as specified by the YQL service
jsonp : 'callback',

// tell jQuery we're expecting JSONP
dataType : 'jsonp',

// tell YQL what we want and that we want JSON
data : {
q : 'select title,abstract,url from search.news where query="cat"',
format : 'json'
},

// work with the response
success : function(response) {
console.log(response);
}
});```

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

## Ajax Events

```\$('#loading_indicator')
.ajaxStart(function() { \$(this).show(); })
.ajaxStop(function() { \$(this).hide(); });```

## How to create a basic plugin

The notation for creating a typical plugin is as follows:

```(function(\$){
\$.fn.myNewPlugin = function() {
return this.each(function(){
// do something
});
};
}(jQuery));```

Don’t let that confuse you though. The point of a jQuery plugin is
to extend jQuery’s prototype object, and that’s what’s happening on this
line:

`\$.fn.myNewPlugin = function() { //...`

We wrap this assignment in an immediately-invoked function:

```(function(\$){
//...
}(jQuery));```

This has the effect of creating a “private” scope that allows us to
extend jQuery using the dollar symbol without having to risk the
possibility that the dollar has been over-written by another
library.

So our actual plugin, thus far, is this:

```\$.fn.myNewPlugin = function() {
return this.each(function(){
// do something
});
};```

The `this` keyword within the new plugin refers to the
jQuery object on which the plugin is being called.

```var somejQueryObject = \$('#something');

\$.fn.myNewPlugin = function() {
};

Your typical jQuery object will contain references to any number of
DOM elements, and that’s why jQuery objects are often referred to as
collections.

So, to do something with a collection we need to loop through it,
which is most easily achieved using jQuery’s `each()`
method:

```\$.fn.myNewPlugin = function() {
return this.each(function(){

});
};```

jQuery’s `each()` method, like most other jQuery methods,
returns a jQuery object, thus enabling what we’ve all come to know and
love as ‘chaining’ (`\$(...).css().attr()...`). We wouldn’t want
to break this convention so we return the `this` object. Within
this loop you can do whatever you want with each element. Here’s an
example of a small plugin using some of the techniques we’ve
discussed:

```(function(\$){
return this.filter('a').each(function(){
\$(this).append(
' (' + \$(this).attr('href') + ')'
);
});
};
}(jQuery));

// Usage example:

This handy plugin goes through all anchors in the collection and
appends the `href` attribute in brackets.

```<!-- Before plugin is called: -->
<a href="page.html">Foo</a>

<!-- After plugin is called: -->
<a href="page.html">Foo (page.html)</a>```

Our plugin can be optimised though:

```(function(\$){
return this.filter('a').append(function(){
return ' (' + this.href + ')';
});
};
}(jQuery));```

We’re using the `append` method’s capability to accept a
callback, and the return value of that callback will determine what is
appended to each element in the collection. Notice also that we’re not
using the `attr` method to retrieve the `href`
attribute, because the native DOM API gives us easy access with the aptly
named `href` property.

Here’s another example of a plugin. This one doesn’t require us to
loop through every elememt with the `each()` method. Instead,
we’re simply going to delegate to other jQuery methods directly:

```(function(\$){
});
};
}(jQuery));

// Usage example:

## Writing Plugins

Sometimes you want to make a piece of functionality available
throughout your code; for example, perhaps you want a single method you
can call on a jQuery selection that performs a series of operations on the
selection. In this case, you may want to write a plugin.

Most plugins are simply methods created in the `\$.fn`
namespace. jQuery guarantees that a method called on a jQuery object will
be able to access that jQuery object as `this` inside the
method. In return, your plugin needs to guarantee that it returns the same
object it received, unless explicitly documented otherwise.

Here is an example of a simple plugin:

Example 8.1. Creating a plugin to add and remove a class on hover

```// defining the plugin
(function(\$){
\$.fn.hoverClass = function(c) {
return this.hover(
function() { \$(this).toggleClass(c); }
);
};
}(jQuery);

// using the plugin
\$('li').hoverClass('hover');```

For more on plugin development, read Mike Alsup’s essential post,
A
Plugin Development Pattern
. In it, he creates a plugin called
`\$.fn.hilight`, which provides support for the metadata plugin
if it’s present, and provides a centralized method for setting global and
instance options for the plugin.

Example 8.2. The Mike Alsup jQuery Plugin Development Pattern

```//
// create closure
//
(function(\$) {
//
// plugin definition
//
\$.fn.hilight = function(options) {
debug(this);
// build main options before element iteration
var opts = \$.extend({}, \$.fn.hilight.defaults, options);
// iterate and reformat each matched element
return this.each(function() {
\$this = \$(this);
// build element specific options
var o = \$.meta ? \$.extend({}, opts, \$this.data()) : opts;
// update element styles
\$this.css({
backgroundColor: o.background,
color: o.foreground
});
var markup = \$this.html();
// call our format function
markup = \$.fn.hilight.format(markup);
\$this.html(markup);
});
};
//
// private function for debugging
//
function debug(\$obj) {
if (window.console && window.console.log)
window.console.log('hilight selection count: ' + \$obj.size());
};
//
// define and expose our format function
//
\$.fn.hilight.format = function(txt) {
return '<strong>' + txt + '</strong>';
};
//
// plugin defaults
//
\$.fn.hilight.defaults = {
foreground: 'red',
background: 'yellow'
};
//
// end of closure
//
})(jQuery);```

## Writing Stateful Plugins with the jQuery UI Widget Factory

### Note

While most existing jQuery plugins are stateless — that is, we
call them on an element and that is the extent of our interaction with the
plugin — there’s a large set of functionality that doesn’t fit into the
basic plugin pattern.

In order to fill this gap, jQuery UI has implemented a more advanced
plugin system. The new system manages state, allows multiple functions to
be exposed via a single plugin, and provides various extension points.
This system is called the widget factory and is exposed as
`jQuery.widget` as part of jQuery UI 1.8; however, it can be
used independently of jQuery UI.

To demonstrate the capabilities of the widget factory, we’ll build a
simple progress bar plugin.

To start, we’ll create a progress bar that just lets us set the
progress once. As we can see below, this is done by calling
`jQuery.widget` with two parameters: the name of the plugin to
create and an object literal containing functions to support our plugin.
When our plugin gets called, it will create a new plugin instance and all
functions will be executed within the context of that instance. This is
different from a standard jQuery plugin in two important ways. First, the
context is an object, not a DOM element. Second, the context is always a
single object, never a collection.

Example 8.3. A simple, stateful plugin using the jQuery UI widget
factory

```\$.widget("nmk.progressbar", {
_create: function() {
var progress = this.options.value + "%";
this.element
.text(progress);
}
});```

The name of the plugin must contain a namespace; in this case we’ve
used the `nmk` namespace. There is a limitation that namespaces
be exactly one level deep — that is, we can’t use a namespace like
`nmk.foo`. We can also see that the widget factory has provided
two properties for us. `this.element` is a jQuery object
containing exactly one element. If our plugin is called on a jQuery object
containing multiple elements, a separate plugin instance will be created
for each element, and each instance will have its own
`this.element`. The second property, `this.options`,
is a hash containing key/value pairs for all of our plugin’s options.
These options can be passed to our plugin as shown here.

Example 8.4. Passing options to a widget

```\$("<div></div>")
.appendTo( "body" )
.progressbar({ value: 20 });```

When we call `jQuery.widget` it extends jQuery by adding
a method to `jQuery.fn` (the same way we’d create a standard
plugin). The name of the function it adds is based on the name you pass to
`jQuery.widget`, without the namespace; in our case it will
create `jQuery.fn.progressbar`. The options passed to our
plugin get set in `this.options` inside of our plugin instance.
As shown below, we can specify default values for any of our options. When
designing your API, you should figure out the most common use case for
your plugin so that you can set appropriate default values and make all
options truly optional.

Example 8.5. Setting default options for a widget

```\$.widget("nmk.progressbar", {
// default options
options: {
value: 0
},

_create: function() {
var progress = this.options.value + "%";
this.element
.text( progress );
}
});```

### Adding Methods to a Widget

Now that we can initialize our progress bar, we’ll add the ability
to perform actions by calling methods on our plugin instance. To define
a plugin method, we just include the function in the object literal that
we pass to `jQuery.widget`. We can also define “private”
methods by prepending an underscore to the function name.

Example 8.6. Creating widget methods

```\$.widget("nmk.progressbar", {
options: {
value: 0
},

_create: function() {
var progress = this.options.value + "%";
this.element
.text(progress);
},

// create a public method
value: function(value) {
// no value passed, act as a getter
if (value === undefined) {
return this.options.value;
// value passed, act as a setter
} else {
this.options.value = this._constrain(value);
var progress = this.options.value + "%";
this.element.text(progress);
}
},

// create a private method
_constrain: function(value) {
if (value > 100) {
value = 100;
}
if (value < 0) {
value = 0;
}
return value;
}
});
```

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

Example 8.7. Calling methods on a plugin instance

```var bar = \$("<div></div>")
.appendTo("body")
.progressbar({ value: 20 });

// get the current value

// update the value
bar.progressbar("value", 50);

// get the current value again

One of the easiest ways to make your plugin extensible is to add
callbacks so users can react when the state of your plugin changes. We
can see below how to add a callback to our progress bar to signify when
the progress has reached 100%. The `_trigger` method takes
three parameters: the name of the callback, a native event object that
initiated the callback, and a hash of data relevant to the event. The
callback name is the only required parameter, but the others can be very
useful for users who want to implement custom functionality on top of
your plugin. For example, if we were building a draggable plugin, we
could pass the native mousemove event when triggering a drag callback;
this would allow users to react to the drag based on the x/y coordinates
provided by the event object.

Example 8.9. Providing callbacks for user extension

```\$.widget("nmk.progressbar", {
options: {
value: 0
},

_create: function() {
this._update();
},

_setOption: function(key, value) {
this.options[key] = value;
this._update();
},

_update: function() {
var progress = this.options.value + "%";
this.element.text(progress);
if (this.options.value == 100) {
this._trigger("complete", null, { value: 100 });
}
}
});```

Callback functions are essentially just additional options, so you
can get and set them just like any other option. Whenever a callback is
executed, a corresponding event is triggered as well. The event type is
determined by concatenating the plugin name and the callback name. The
callback and event both receive the same two parameters: an event object
and a hash of data relevant to the event, as we’ll see below.

If your plugin has functionality that you want to allow the user
to prevent, the best way to support this is by creating cancelable
callbacks. Users can cancel a callback, or its associated event, the
same way they cancel any native event: by calling
`event.preventDefault()` or using `return false`.
If the user cancels the callback, the `_trigger` method will
return false so you can implement the appropriate functionality within

Example 8.10. Binding to widget events

```var bar = \$("<div></div>")
.appendTo("body")
.progressbar({
complete: function(event, data) {
}
})
.bind("progressbarcomplete", function(event, data) {
alert("Events bubble and support many handlers for extreme flexibility.");
alert("The progress bar value is " + data.value);
});

bar.progressbar("option", "value", 100);```

### Cleaning Up

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

Example 8.11. Adding a destroy method to a widget

```\$.widget( "nmk.progressbar", {
options: {
value: 0
},

_create: function() {
this._update();
},

_setOption: function(key, value) {
this.options[key] = value;
this._update();
},

_update: function() {
var progress = this.options.value + "%";
this.element.text(progress);
if (this.options.value == 100 ) {
this._trigger("complete", null, { value: 100 });
}
},

destroy: function() {
this.element
.removeClass("progressbar")
.text("");

// call the base destroy function
\$.Widget.prototype.destroy.call(this);
}
});```

to contribute!

## Cache length during loops

In a for loop, don’t access the length property of an array every
time; cache it beforehand.

```var myLength = myArray.length;

for (var i = 0; i < myLength; i++) {
// do stuff
}```

## Append new content outside of a loop

Touching the DOM comes at a cost; if you’re adding a lot of elements
to the DOM, do it all at once, not one at a time.

```// this is bad
\$.each(myArray, function(i, item) {
var newListItem = '<li>' + item + '</li>';
\$('#ballers').append(newListItem);
});

// better: do this
var frag = document.createDocumentFragment();

\$.each(myArray, function(i, item) {
var newListItem = '<li>' + item + '</li>';
frag.appendChild(newListItem);
});
\$('#ballers')[0].appendChild(frag);

// or do this
var myHtml = '';

\$.each(myArray, function(i, item) {
html += '<li>' + item + '</li>';
});
\$('#ballers').html(myHtml);```

## Keep things DRY

Don’t repeat yourself; if you’re repeating yourself, you’re doing it
wrong.

```// BAD
}

if (\$eventhover.data('currently') != 'showing') {
\$eventhover.stop();
}

if (\$spans.data('currently') != 'showing') {
\$spans.stop();
}

// GOOD!!
var \$elems = [\$eventfade, \$eventhover, \$spans];
\$.each(\$elems, function(i,elem) {
if (elem.data('currently') != 'showing') {
elem.stop();
}
});```

## Beware anonymous functions

Anonymous functions bound everywhere are a pain. They’re difficult
to debug, maintain, test, or reuse. Instead, use an object literal to
organize and name your handlers and callbacks.

```// BAD
\$('#magic').click(function(e) {
\$('#yayeffects').slideUp(function() {
// ...
});
});

\$('#happiness').load(url + ' #unicorns', function() {
// ...
});
});

// BETTER
var PI = {
\$('#magic').click(PI.candyMtn);
},

candyMtn : function(e) {
\$('#yayeffects').slideUp(PI.slideCb);
},

slideCb : function() { ... },

unicornCb : function() { ... }
};

## Optimize Selectors

Selector optimization is less important than it used to be, as more
browser implement `document.querySelectorAll()` and the burden
of selection shifts from jQuery to the browser. However, there are still
some tips to keep in midn.

### Avoid the Universal Selector

Selections that specify or imply that a match could be found
anywhere can be very slow.

```\$('.buttons > *');  // extremely expensive
\$('.buttons').children();  // much better

\$('.gender :radio');  // implied universal selection
\$('.gender *:radio'); // same thing, explicit now

## Detach Elements to Work With Them

The DOM is slow; you want to avoid manipulating it as much as
possible. jQuery introduced `\$.fn.detach` in version 1.4 to
help address this issue, allowing you to remove an element from the DOM
while you work with it.

```var \$table = \$('#myTable');
var \$parent = table.parent();

\$table.detach();
// ... add lots and lots of rows to table
\$parent.append(table);```

## Use Stylesheets for Changing CSS on Many Elements

If you’re changing the CSS of more than 20 elements using \$.fn.css,
consider adding a style tag to the page instead for a nearly 60% increase
in speed.

```// fine for up to 20 elements, slow after that
\$('a.swedberg').css('color', '#asd123');
\$('<style type="text/css">a.swedberg { color : #asd123 }</style>')

## Use `\$.data` Instead of `\$.fn.data`

Using \$.data on a DOM element instead of calling \$.fn.data on a
jQuery selection can be up to 10 times faster. Be sure you understand the
difference between a DOM element and a jQuery selection before doing this,
though.

`// regular \$(elem).data(key,value);    // 10x faster  \$.data(elem,key,value);`

## Don’t Act on Absent Elements

jQuery won’t tell you if you’re trying to run a whole lot of code on
an empty selection — it will proceed as though nothing’s wrong. It’s up to
you to verify that your selection contains some elements.

`// BAD: this runs three functions // before it realizes there's nothing // in the selection \$('#nosuchthing').slideUp();  // Better var \$mySelection = \$('#nosuchthing'); if (\$mySelection.length) { mySelection.slideUp(); }  // BEST: add a doOnce plugin jQuery.fn.doOnce = function(func){     this.length && func.apply(this);     return this;  }   \$('li.cartitems').doOnce(function(){     // make it ajax! \o/ });`

This guidance is especially applicable for jQuery UI widgets, which
have a lot of overhead even when the selection doesn’t contain
elements.

## Variable Definition

Variables can be defined in one statement instead of several.

```// old & busted
var test = 1;
var test2 = function() { ... };
var test3 = test2(test);

// new hotness
var test = 1,
test2 = function() { ... },
test3 = test2(test);```

In self-executing functions, variable definition can be skipped all
together.

`(function(foo, bar) { ... })(1, 2);`

## Conditionals

```// old way
if (type == 'foo' || type == 'bar') { ... }

// better
if (/^(foo|bar)\$/.test(type)) { ... }

// object literal lookup
if (({ foo : 1, bar : 1 })[type]) { ... }```

## Don’t Treat jQuery as a Black Box

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

## Overview

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

## Encapsulation

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

### The Object Literal

An object literal is perhaps the simplest way to encapsulate
related code. It doesn’t offer any privacy for properties or methods,
but it’s useful for eliminating anonymous functions from your code,
centralizing configuration options, and easing the path to reuse and
refactoring.

Example 10.1. An object literal

```var myFeature = {
myProperty : 'hello',

myMethod : function() {
console.log(myFeature.myProperty);
},

init : function(settings) {
myFeature.settings = settings;
},

console.log(myFeature.settings);
}
};

myFeature.myProperty; // 'hello'
myFeature.myMethod(); // logs 'hello'
myFeature.init({ foo : 'bar' });
myFeature.readSettings(); // logs { foo : 'bar' }
```

The object literal above is simply an object assigned to a
variable. The object has one property and several methods. All of the
properties and methods are public, so any part of your application can
see the properties and call methods on the object. While there is an
init method, there’s nothing requiring that it be called before the
object is functional.

How would we apply this pattern to jQuery code? Let’s say that we

```// clicking on a list item loads some content
// using the list item's ID and hides content
// in sibling list items
\$('#myFeature li')
.append('<div/>')
.click(function() {
var \$this = \$(this);
var \$div = \$this.find('div');
\$this.attr('id'),
function() {
\$div.show();
\$this.siblings()
.find('div').hide();
}
);
});
});
```

If this were the extent of our application, leaving it as-is would
be fine. On the other hand, if this was a piece of a larger application,
we’d do well to keep this functionality separate from unrelated
functionality. We might also want to move the URL out of the code and
into a configuration area. Finally, we might want to break up the chain
to make it easier to modify pieces of the functionality later.

Example 10.2. Using an object literal for a jQuery feature

```var myFeature = {
init : function(settings) {
myFeature.config = {
\$items : \$('#myFeature li'),
\$container : \$('<div class="container"></div>'),
urlBase : '/foo.php?item='
};

// allow overriding the default config
\$.extend(myFeature.config, settings);

myFeature.setup();
},

setup : function() {
myFeature.config.\$items
.each(myFeature.createContainer)
.click(myFeature.showItem);
},

createContainer : function() {
var \$i = \$(this),
\$c = myFeature.config.\$container.clone()
.appendTo(\$i);

\$i.data('container', \$c);
},

buildUrl : function() {
return myFeature.config.urlBase +
myFeature.\$currentItem.attr('id');
},

showItem : function() {
var myFeature.\$currentItem = \$(this);
myFeature.getContent(myFeature.showContent);
},

getContent : function(callback) {
var url = myFeature.buildUrl();
myFeature.\$currentItem
},

showContent : function() {
myFeature.\$currentItem
.data('container').show();
myFeature.hideContent();
},

hideContent : function() {
myFeature.\$currentItem.siblings()
.each(function() {
\$(this).data('container').hide();
});
}
};

The first thing you’ll notice is that this approach is obviously
far longer than the original — again, if this were the extent of our
application, using an object literal would likely be overkill. Assuming
it’s not the extent of our application, though, we’ve gained several
things:

For non-trivial features, object literals are a clear improvement
over a long stretch of code stuffed in a \$(document).ready() block, as
they get us thinking about the pieces of our functionality. However,
they aren’t a whole lot more advanced than simply having a bunch of
function declarations inside of that \$(document).ready() block.

### The Module Pattern

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

Example 10.3. The module pattern

```var feature =(function() {

// private variables and functions
var privateThing = 'secret',
publicThing = 'not secret',

changePrivateThing = function() {
privateThing = 'super secret';
},

sayPrivateThing = function() {
console.log(privateThing);
changePrivateThing();
};

// public API
return {
publicThing : publicThing,
sayPrivateThing : sayPrivateThing
}

})();

feature.publicThing; // 'not secret'

feature.sayPrivateThing();
// logs 'secret' and changes the value
// of privateThing```

In the example above, we self-execute an anonymous function that
returns an object. Inside of the function, we define some variables.
Because the variables are defined inside of the function, we don’t have
access to them outside of the function unless we put them in the return
object. This means that no code outside of the function has access to
the `privateThing` variable or to the
`changePrivateThing` function. However,
`sayPrivateThing` does have access to
`privateThing` and `changePrivateThing`, because
both were defined in the same scope as
`sayPrivateThing`.

This pattern is powerful because, as you can gather from the
variable names, it can give you private variables and functions while
exposing a limited API consisting of the returned object’s properties
and methods.

Below is a revised version of the previous example, showing how we
could create the same feature using the module pattern while only
exposing one public method of the module,
`showItemByIndex()`.

Example 10.4. Using the module pattern for a jQuery feature

```\$(document).ready(function() {
var feature = (function() {

var \$items = \$('#myFeature li'),
\$container = \$('<div class="container"></div>'),
\$currentItem,

urlBase = '/foo.php?item=',

createContainer = function() {
var \$i = \$(this),
\$c = \$container.clone().appendTo(\$i);

\$i.data('container', \$c);
},

buildUrl = function() {
return urlBase + \$currentItem.attr('id');
},

showItem = function() {
var \$currentItem = \$(this);
getContent(showContent);
},

showItemByIndex = function(idx) {
\$.proxy(showItem, \$items.get(idx));
},

getContent = function(callback) {
},

showContent = function() {
\$currentItem.data('container').show();
hideContent();
},

hideContent = function() {
\$currentItem.siblings()
.each(function() {
\$(this).data('container').hide();
});
};

\$items
.each(createContainer)
.click(showItem);

return { showItemByIndex : showItemByIndex };
})();

feature.showItemByIndex(0);
});```

## Managing Dependencies

### Note

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

When a project reaches a certain size, managing the script modules
for a project starts to get tricky. You need to be sure to sequence the
scripts in the right order, and you need to start seriously thinking about
combining scripts together into a bundle for deployment, so that only one
or a very small number of requests are made to load the scripts. You may

manage the script modules, load them in the right order, and make it easy
to combine the scripts later via the RequireJS optimization tool without
needing to change your markup. It also gives you an easy way to load
size over time.

RequireJS has a module system that lets you define well-scoped
modules, but you do not have to follow that system to get the benefits of
dependency management and build-time optimizations. Over time, if you
start to create more modular code that needs to be reused in a few places,
the module format for RequireJS makes it easy to write encapsulated code
that can be loaded on the fly. It can grow with you, particularly if you
want to incorporate internationalization (i18n) string bundles, to
and make sure those strings are available before executing code, or even
use JSONP services as dependencies.

### Getting RequireJS

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

### Using RequireJS with jQuery

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

Example 10.5. Using RequireJS: A simple example

```<!DOCTYPE html>
<html>
<title>jQuery+RequireJS Sample Page</title>
<script src="scripts/require-jquery.js"></script>
<script>require(["app"]);</script>
<body>
<h1>jQuery+RequireJS Sample Page</h1>
</body>
</html>```

The call to `require(["app"])` tells RequireJS to load
the `scripts/app.js` file. RequireJS will load any
dependency that is passed to `require()` without a
`.js` extension from the same directory as
`require-jquery.js`, though this can be configured to
behave differently. If you feel more comfortable specifying the whole
path, you can also do the following:

`<script>require(["scripts/app.js"]);</script>`

What is in `app.js`? Another call to
`require.js` to load all the scripts you need and any
init work you want to do for the page. This example
`app.js` script loads two plugins,
`jquery.alpha.js` and
`jquery.beta.js` (not the names of real plugins, just
an example). The plugins should be in the same directory as
`require-jquery.js`:

Example 10.6. A simple JavaScript file with dependencies

```require(["jquery.alpha", "jquery.beta"], function() {
//the jquery.alpha.js and jquery.beta.js plugins have been loaded.
\$(function() {
\$('body').alpha().beta();
});
});```

### Creating Reusable Modules with RequireJS

RequireJS makes it easy to define reusable modules via
`require.def()`. A RequireJS module can have dependencies
that can be used to define a module, and a RequireJS module can return a
value — an object, a function, whatever — that can then be consumed by
yet other modules.

If your module does not have any dependencies, then just specify
the name of the module as the first argument to
`require.def()`. The second argument is just an object
literal that defines the module’s properties. For example:

Example 10.7. Defining a RequireJS module that has no dependencies

```require.def("my/simpleshirt",
{
color: "black",
size: "unisize"
}
);```

This example would be stored in a my/simpleshirt.js file.

If your module has dependencies, you can specify the
dependencies as the second argument to `require.def()` (as
an array) and then pass a function as the third argument. The function
will be called to define the module once all dependencies have loaded.
The function receives the values returned by the dependencies as its
arguments (in the same order they were required in the array), and the
function should return an object that defines the module.

Example 10.8. Defining a RequireJS module with dependencies

```require.def("my/shirt",
["my/cart", "my/inventory"],
function(cart, inventory) {
//return an object to define the "my/shirt" module.
return {
color: "blue",
size: "large"
inventory.decrement(this);
}
}
}
);```

In this example, a my/shirt module is created. It depends on
my/cart and my/inventory. On disk, the files are structured like this:

```my/cart.js
my/inventory.js
my/shirt.js```

The function that defines `my/shirt` is not called
until the `my/cart` and `my/inventory` modules
`cart` and `inventory` arguments. The order of
the function arguments must match the order in which the dependencies
were required in the dependencies array. The object returned by the
function call defines the `my/shirt` module. Be defining
modules in this way, `my/shirt` does not exist as a global
object. Modules that define globals are explicitly discouraged, so
multiple versions of a module can exist in a page at a time.

Modules do not have to return objects; any valid return value
from a function is allowed.

Example 10.9. Defining a RequireJS module that returns a function

```require.def("my/title",
["my/dependency1", "my/dependency2"],
function(dep1, dep2) {
//return a function to define "my/title". It gets or sets
//the window title.
return function(title) {
return title ? (window.title = title) : window.title;
}
}
);```

Only one module should be required per JavaScript file.

### Optimizing Your Code: The RequireJS Build Tool

Once you incorporate RequireJS for dependency management, your
page is set up to be optimized very easily. Download the RequireJS
source and place it anywhere you like, preferrably somewhere outside
your web development area. For the purposes of this example, the
RequireJS source is placed as a sibling to the
`webapp` directory, which contains the HTML page and
the scripts directory with all the scripts. Complete directory
structure:

```requirejs/ (used for the build tools)
webapp/app.html
webapp/scripts/app.js
webapp/scripts/require-jquery.js
webapp/scripts/jquery.alpha.js
webapp/scripts/jquery.beta.js```

Then, in the scripts directory that has
`require-jquery.js` and app.js, create a file called
app.build.js with the following contents:

Example 10.10. A RequireJS build configuration file

```{
appDir: "../",
baseUrl: "scripts/",
dir: "../../webapp-build",
//Comment out the optimize line if you want
//the code minified by Closure Compiler using
//the "simple" optimizations mode
optimize: "none",

modules: [
{
name: "app"
}
]
}```

To use the build tool, you need Java 6 installed. Closure Compiler
is used for the JavaScript minification step (if ```optimize: "none"``` is commented out), and it requires Java 6.

To start the build, go to the webapp/scripts directory, execute
the following command:

```# non-windows systems
../../requirejs/build/build.sh app.build.js

# windows systems
..\..\requirejs\build\build.bat app.build.js```

Now, in the webapp-build directory, `app.js`
will have the `app.js` contents,
`jquery.alpha.js` and
`jquery.beta.js` inlined. If you then load the
`app.html` file in the
`webapp-build` directory, you should not see any
network requests for `jquery.alpha.js` and
`jquery.beta.js`.

## Exercises

### Create a Portlet Module

Open the file `/exercises/portlets.html` in
`/exercises/js/portlets.js`. Your task is to create a
portlet creation function that uses the module pattern, such that the
following code will work:

```var myPortlet = Portlet({
title : 'Curry',
source : 'data/html/curry.html',
initialState : 'open' // or 'closed'
});

myPortlet.\$element.appendTo('body');```

Each portlet should be a div with a title, a content area, a
button to open/close the portlet, a button to remove the portlet, and a
button to refresh the portlet. The portlet returned by the Portlet
function should have the following public API:

```myPortlet.open(); // force open state
myPortlet.close(); // force close state
myPortlet.toggle(); // toggle open/close state
myPortlet.refresh(); // refresh the content
myPortlet.destroy(); // remove the portlet from the page
myPortlet.setSource('data/html/onions.html');
// change the source```

## Introducing Custom Events

We’re all familiar with the basic events — click, mouseover, focus,
blur, submit, etc. — that we can latch on to as a user interacts with the
browser. Custom events open up a whole new world of event-driven
programming. In this chapter, we’ll use jQuery’s custom events system to
make a simple Twitter search application.

It can be difficult at first to understand why you’d want to use
custom events, when the built-in events seem to suit your needs just fine.
It turns out that custom events offer a whole new way of thinking about
event-driven JavaScript. Instead of focusing on the element that triggers
an action, custom events put the spotlight on the element being acted
upon. This brings a bevy of benefits, including:

Why should you care? An example is probably the best way to explain.
Suppose you have a lightbulb in a room in a house. The lightbulb is
currently turned on, and it’s controlled by two three-way switches and a
clapper:

```<div class="room" id="kitchen">
<div class="lightbulb on"></div>
<div class="switch"></div>
<div class="switch"></div>
<div class="clapper"></div>
</div>```

Triggering the clapper or either of the switches will change the
state of the lightbulb. The switches and the clapper don’t care what state
the lightbulb is in; they just want to change the state.

Without custom events, you might write some code like this:

```\$('.switch, .clapper').click(function() {
var \$light = \$(this).parent().find('.lightbulb');
if (\$light.hasClass('on')) {
} else {
}
});```

With custom events, your code might look more like this:

```\$('.lightbulb').bind('changeState', function(e) {
var \$light = \$(this);
if (\$light.hasClass('on')) {
} else {
}
});

\$('.switch, .clapper').click(function() {
\$(this).parent().find('.lightbulb').trigger('changeState');
});```

This last bit of code is not that exciting, but something important
has happened: we’ve moved the behavior of the lightbulb to the lightbulb,
and away from the switches and the clapper.

Let’s make our example a little more interesting. We’ll add another
room to our house, along with a master switch, as shown here:

```<div class="room" id="kitchen">
<div class="lightbulb on"></div>
<div class="switch"></div>
<div class="switch"></div>
<div class="clapper"></div>
</div>
<div class="room" id="bedroom">
<div class="lightbulb on"></div>
<div class="switch"></div>
<div class="switch"></div>
<div class="clapper"></div>
</div>
<div id="master_switch"></div>```

If there are any lights on in the house, we want the master switch
to turn all the lights off; otherwise, we want it to turn all lights on.
To accomplish this, we’ll add two more custom events to the lightbulbs:
`turnOn` and `turnOff`. We’ll make use of them in
the `changeState` custom event, and use some logic to decide
which one the master switch should trigger:

```\$('.lightbulb')
.bind('changeState', function(e) {
var \$light = \$(this);
if (\$light.hasClass('on')) {
\$light.trigger('turnOff');
} else {
\$light.trigger('turnOn');
}
})
.bind('turnOn', function(e) {
})
.bind('turnOff', function(e) {
});

\$('.switch, .clapper').click(function() {
\$(this).parent().find('.lightbulb').trigger('changeState');
});

\$('#master_switch').click(function() {
if (\$('.lightbulb.on').length) {
\$('.lightbulb').trigger('turnOff');
} else {
\$('.lightbulb').trigger('turnOn');
}
});```

Note how the behavior of the master switch is attached to the master
switch; the behavior of a lightbulb belongs to the lightbulbs.

### A Sample Application

To demonstrate the power of custom events, we’re going to create a
simple tool for searching Twitter. The tool will offer several ways for
a user to add search terms to the display: by entering a search term in
a text box, by entering multiple search terms in the URL, and by

The results for each term will be shown in a results container;
these containers will be able to be expanded, collapsed, refreshed, and
removed, either individually or all at once.

When we’re done, it will look like this:

#### The Setup

```<h1>Twitter Search</h1>
<input type="button" id="get_trends"

<form>
<input type="text" class="input_text"
id="search_term" />
<input type="submit" class="input_submit"
</form>

<div class="template results">
<h2>Search Results for
<span class="search_term"></span></h2>
</div>
</div>```

This gives us a container (#twitter) for our widget, a template
for our results containers (hidden via CSS), and a simple form where
users can input a search term. (For the sake of simplicity, we’re
going to assume that our application is JavaScript-only and that our
users will always have CSS.)

There are two types of objects we’ll want to act on: the results

The results containers are the heart of the application. We’ll
create a plugin that will prepare each results container once it’s
added to the Twitter container. Among other things, it will bind the
custom events for each container and add the action buttons at the top
right of each container. Each results container will have the
following custom events:

The plugin is also responsible for adding the action buttons to
the container. It binds a click event to each action’s list item, and
uses the list item’s class to determine which custom event will be
triggered on the corresponding results container.

```\$.fn.twitterResult = function(settings) {
return \$(this).each(function() {
var \$results = \$(this),
\$a = \$actions.clone().prependTo(\$results),
term = settings.term;

\$results.find('span.search_term').text(term);

\$.each(
['refresh', 'populate', 'remove', 'collapse', 'expand'],
function(i, ev) {
\$results.bind(
ev,
{ term : term },
);
}
);

// use the class of each action to figure out
// which event it will trigger on the results panel
\$a.find('li').click(function() {
// pass the li that was clicked to the function
// so it can be manipulated if needed
\$results.trigger(\$(this).attr('class'), [ \$(this) ]);
});
});
};

return \$('<ul class="actions" />').append(
'<li class="refresh">Refresh</li>' +
'<li class="remove">Remove</li>' +
'<li class="collapse">Collapse</li>'
);
};

refresh : function(e) {
// indicate that the results are refreshing

\$this.find('p.tweet').remove();

// get the twitter data using jsonp
\$.getJSON(
escape(e.data.term) + '&rpp=5&callback=?',
function(json) {
\$this.trigger('populate', [ json ]);
}
);
},

populate : function(e, json) {
var results = json.results;
var \$this = \$(this);

\$.each(results, function(i,result) {
var tweet = '<p class="tweet">' +
result.from_user +
'">' +
result.from_user +
'</a>: ' +
result.text +
' <span class="date">' +
result.created_at +
'</span>' +
'</p>';
\$this.append(tweet);
});

// indicate that the results
// are done refreshing
\$this.removeClass('refreshing');
},

remove : function(e, force) {
if (
!force &&
!confirm('Remove panel for term ' + e.data.term + '?')
) {
return;
}
\$(this).remove();

// indicate that we no longer
// have a panel for the term
search_terms[e.data.term] = 0;
},

collapse : function(e) {
\$(this).find('li.collapse').removeClass('collapse')

},

expand : function(e) {
\$(this).find('li.expand').removeClass('expand')

\$(this).removeClass('collapsed');
}
};```

The Twitter container itself will have just two custom events:

Here’s how the Twitter container bindings look:

```\$('#twitter')
.bind('getResults', function(e, term) {
// make sure we don't have a box for this term already
if (!search_terms[term]) {
var \$this = \$(this);
var \$template = \$this.find('div.template');

// make a copy of the template div
// and insert it as the first results box
\$results = \$template.clone().
removeClass('template').
insertBefore(\$this.find('div:first')).
'term' : term
});

// load the content using the "refresh"
// custom event that we bound to the results container
\$results.trigger('refresh');
search_terms[term] = 1;
}
})
.bind('getTrends', function(e) {
var \$this = \$(this);
var trends = json.trends;
\$.each(trends, function(i, trend) {
\$this.trigger('getResults', [ trend.name ]);
});
});
});```

So far, we’ve written a lot of code that does approximately
nothing, but that’s OK. By specifying all the behaviors that we want
our core objects to have, we’ve created a solid framework for rapidly
building out the interface.

Let’s start by hooking up our text input and the “Load Trending
Terms” button. For the text input, we’ll capture the term that was
entered in the input and pass it as we trigger the Twitter container’s
`getResults` event. Clicking the “Load Trending Terms” will
trigger the Twitter container’s `getTrends` event:

```\$('form').submit(function(e) {
e.preventDefault();
var term = \$('#search_term').val();
});

\$('#get_trends').click(function() {
});```

By adding a few buttons with the appropriate IDs, we can make it
possible to remove, collapse, expand, and refresh all results
containers at once, as shown below. For the remove button, note how
we’re passing a value of true to the event handler as its second
argument, telling the event handler that we don’t want to verify the
removal of individual containers.

```\$.each(['refresh', 'expand', 'collapse'], function(i, ev) {
\$('#' + ev).click(function(e) { \$('#twitter div.results').trigger(ev); });
});

\$('#remove').click(function(e) {
if (confirm('Remove all results?')) {
}
});```

My Developer Forum is a non-profit, open source website dedicated to empowering young, eager designers and developers to take the web to a higher level of complexity, and elegance.
This entry was posted in cis mhcc, CSS & HTML, Featured, jQuery, Kitchen Sink and tagged . Bookmark the permalink.

### 19 Responses to jQuery Documentation

1. Travel Deals says:

Hi I like this article and it was so fabulous and I am definetly going to save it. I Have to say the Superb analysis this article has is trully remarkable.Who goes that extra mile these days? Bravo :) Just another suggestion you caninstall a Translator for your Worldwide Readers !!!

good call – I think I will

2. Sometimes I lie awake at night, and I ask, ‘Where have I gone wrong?’ Then a voice says to me, ‘This is going to take more than one night.’ !l13w!

Way to focus and straight to your point, i love it. Keep up the work people. Dont let anyone stop us bloggers.

4. Thank you for give very nice info What a cool site.

5. Viva Palardy says:

6. Can I make a suggestion? I think youve got something good here. But what if you added a couple links to a page that backs up what youre saying? Or maybe you could give us something to look at, something that would connect what youre saying to something tangible? Just a suggestion.

Feel free to Submit stuff you find – I will be slowing down with new posts due to a heavier work load

7. The new Zune browser is surprisingly good, but not as good as the iPod’s. It works well, but isn’t as fast as Safari, and has a clunkier interface. If you occasionally plan on using the web browser that’s not an issue, but if you’re planning to browse the web alot from your PMP then the iPod’s larger screen and better browser may be important.

8. Cool post, thank you for the info – I dont really ever post on these thingy’s but enjoyed the info. Awesome stuff!, I bookmarked your blog!

9. Jenny says:

Greetings, I I stumbled upon your site on yahoo and browse pretty much all your other pages. I just added you to my RSS feeder. Keep up the amazing job. Looking forward to reading more from you in the future. You know, I must say, I really enjoy this site and the insight from everyone who participates. I find it to be refreshing and very informative. I wish there were more blogs like it. Anyway, I felt it was about time I posted, I?ve spent most of my time here just lurking and reading, but today for some reason I just felt compelled to say this.

10. frostwire says:

Hello there, You’ve done an incredible job. I’ll certainly digg it and personally suggest to my friends. I am sure they will be benefited from this website.

11. Your post fashion and blog page template are not harmonious, transform a good blog’s template.

12. Halley Hemp says:

I am constantly looking online for posts that can facilitate me. Thank you!

13. frostwire says:

Hi there, You have done an excellent job. I’ll definitely digg it and personally suggest to my friends. I’m sure they’ll be benefited from this site.

14. Xnxx says:

Interesting thoughts here. I appreciate you taking the time to share them with us all. It’s people like you that make my day :)

15. Corset Tops says:

“~. I am very thankful to this topic because it really gives up to date information “`.

16. UV Paint says:

:”‘ that seems to be a great topic, i really love it .~”

17. Eldon Bussy says:

Great beat ! I would like to apprentice at the same time as you amend your website, how could i subscribe for a weblog site? The account helped me a applicable deal. I were tiny bit acquainted of this your broadcast offered vibrant transparent idea