jQuery 1.4 was recently released. This wasn't simply a maintenance release as some had speculated; there are many
new features, enhancements and performance improvements included in
1.4! This post covers the new features and enhancements that you may
find beneficial.
You can download jQuery 1.4 right now, here: http://code.jquery.com/jquery-1.4.js
Let's say you need to create an anchor element with several attributes. With 1.4 it's as simple as:
You may have noticed the "
A better example of this in action:
The "id" is added as a regular attribute, but the "css" and "click"
properties trigger calling of each respective method. The above code,
before the 1.4 release, would have been written like this:
You want to select all of items after "Apple", but you want to stop once you reach "Strawberry". It couldn't be simpler:
This also works with "
To specify an easing function for each property simply define the property as an array, with the first value being what you want to animate that property to, and the second being the easing function to use:
You can also define per-property easing functions in the optional options object as property name-value pairs in the "specialEasing" object:
Editor's Note - The author of this article, James Padolsey, is being modest. This new feature was his idea!
But, be careful! You must use the event names, "focusin" and "focusout" if you want to delegate the "focus" and "blur" events!
For example, here we've got an "
The "
Let's try binding it as an event handler:
When we click an anchor it doesn't appear to work (nothing is
alerted). That's because jQuery (and most sane event models) will, by
default, set the context of the handler as the target element,- that is,
the element that's just been clicked will be accessible via "
Now whenever an anchor is clicked, "Hi!" will be alerted!
The proxy function returns a "wrapped" version of your function, with "
If you want to delay a queue other than the default "fx" queue, then
you'll need to pass the queue name as the second argument to "
That would select all DIV elements that contain UL elements. In this situation you'd probably just use the selector filter ("
jQuery 1.4 also reveals the "
We can unwrap the paragraph element like so:
The resulting DOM structure would be:
Essentially, this method simply removes the parent of any element.
This can be useful when you need to remove an element from the DOM, but you know you'll need to add it back at a later stage. Its event handlers and any other data will persist.
Passing no arguments now returns the index of an element amongst its siblings. So, assuming the following DOM structure:
When a list item is clicked you want to find out the index of the
clicked element amongst all the other list items. It's as simple as:
jQuery 1.4 also allows you to specify a selector as the first argument to "
You should note that what's returned from this method is an integer, and it will return -1 if the selector/element passed cannot be found in the document.
The following methods have this capability:
Also, with some of the above methods you'll also get a second argument. If you're calling a setter method (like "
As you can see, with the "
First, there's "
Read more about:
In addition, it now accepts a context as the second argument, meaning that you can control just how far or how close you want the DOM traversed to. Both of these enhancements accommodate rare use cases but they are used internally to great effect!
Read more about
You should also note that both of these events do not propagate ("bubble"); they are captured. This means that the outermost (ancestor) element will be triggered before the causal "target" element.
You can download jQuery 1.4 right now, here: http://code.jquery.com/jquery-1.4.js
1. Passing Attributes to jQuery(…)
Pre 1.4, jQuery supported adding attributes to an element collection via the useful "attr
"
method, which can be passed both an attribute name and value, or an
object specifying several attributes. jQuery 1.4 adds support for
passing an attributes object as the second argument to the jQuery
function itself, upon element creation.Let's say you need to create an anchor element with several attributes. With 1.4 it's as simple as:
1
2
3
4
5
6
7
| jQuery( '<a/>' , { id: 'foo' , title: 'Become a Googler' , rel: 'external' , text: 'Go to Google!' }); |
text
" attribute— you'll probably be wondering what that's doing there, after all there's no "text
"
attribute for anchors! Well, jQuery 1.4 utilises its very own methods
when you pass certain attributes. So the "text" attribute specified
above would cause jQuery to call the ".text()
" method, passing "Go to Google!" as its only argument.A better example of this in action:
01
02
03
04
05
06
07
08
09
10
| jQuery( '<div/>' , { id: 'foo' , css: { fontWeight: 700, color: 'green' }, click: function (){ alert( 'Foo has been clicked!' ); } }); |
1
2
3
4
5
6
7
8
9
| jQuery( '<div/>' ) .attr( 'id' , 'foo' ) .css({ fontWeight: 700, color: 'green' }) .click( function (){ alert( 'Foo has been clicked!' ); }); |
2. Everything "until"!
Three new methods have been added to the DOM traversal arsenal in 1.4, "nextUntil
", "prevUntil
" and "parentsUntil
".
Each of these methods will traverse the DOM in a certain direction
until the passed selector is satisfied. So, let's say you have a list of
fruit:
1
2
3
4
5
6
7
8
9
| < ul > < li >Apple</ li > < li >Banana</ li > < li >Grape</ li > < li >Strawberry</ li > < li >Pear</ li > < li >Peach</ li > </ ul > |
1
2
| jQuery( 'ul li:contains(Apple)' ).nextUntil( ':contains(Pear)' ); // Selects Banana, Grape, Strawberry |
3. Binding Multiple Event Handlers
Instead of chaining a bunch of event binding methods together, you can lump them all into the same call, like so:
01
02
03
04
05
06
07
08
09
10
11
| jQuery(' #foo).bind({ click: function () { // do something }, mouseover: function () { // do something }, mouseout: function () { // do something } }) |
.one()
".4. Per-Property Easing
Instead of just defining one easing function for a single animation, you can now define a different easing function for each property that you're animating. jQuery includes two easing functions, swing (the default) and linear. For other ones you'll need to download them separately!To specify an easing function for each property simply define the property as an array, with the first value being what you want to animate that property to, and the second being the easing function to use:
1
2
3
4
| jQuery( '#foo' ).animate({ left: 500, top: [500, 'easeOutBounce' ] }, 2000); |
You can also define per-property easing functions in the optional options object as property name-value pairs in the "specialEasing" object:
1
2
3
4
5
6
7
8
9
| jQuery( '#foo' ).animate({ left: 500, top: 500 }, { duration: 2000, specialEasing: { top: 'easeOutBounce' } }); |
5. New Live Events!
jQuery 1.4 adds support for delegating the "submit", "change", "focus" and "blur" events. In jQuery, we use the ".live()
"
method to delegate events. This is useful when you have to register
event handlers on many elements, and when new elements may be added over
time (using ".live()
" is less-costly than re-binding continually).But, be careful! You must use the event names, "focusin" and "focusout" if you want to delegate the "focus" and "blur" events!
1
2
3
| jQuery( 'input' ).live( 'focusin' , function (){ // do something with this }); |
6. Controlling a Function's Context
jQuery 1.4 provides a new "proxy
" function under the
jQuery namespace. This function takes two arguments, either a "scope"
and a method name, or a function and the intended scope. JavaScript's
"this" keyword can be quite tricky to keep a hold of. Sometimes you
won't want it to be an element, but instead an object that you've
previously created.For example, here we've got an "
app
" object which has two properties, a "clickHandler
" method and a config object:
1
2
3
4
5
6
7
8
| var app = { config: { clickMessage: 'Hi!' }, clickHandler: function () { alert( this .config.clickMessage); } }; |
clickHandler
" method, when called like "app.clickHandler()
" will have "app
" as its context, meaning that the "this
" keyword will allow it access to "app
". This works quite well if we simply call:
1
| app.clickHandler(); // "Hi!" is alerted |
1
| jQuery( 'a' ).bind( 'click' , app.clickHandler); |
this
". But we don't want that, we want "this
" to be set to "app
". Achieving this in jQuery 1.4 couldn't be simpler:
1
2
3
4
| jQuery( 'a' ).bind( 'click' , jQuery.proxy(app, 'clickHandler' ) ); |
The proxy function returns a "wrapped" version of your function, with "
this
"
set to whatever you specify. It's useful in other contexts too, such as
passing callbacks to other jQuery methods, or to plugins.7. Delay an Animation Queue
You can now add a delay to your animation queues. In fact, this works on any queue, but its most common use case will probably be with the "fx" queue. This allows you to pause between animations without having to mess with callbacks and calls to "setTimeout
". The first argument to ".delay()
" is the amount of milliseconds you want to delay for.
1
2
3
4
| jQuery( '#foo' ) .slideDown() // Slide down .delay(200) // Do nothing for 200 ms .fadeIn(); // Fade in |
.delay()
".8. Check if an Element Has Something
jQuery 1.4 makes it easy to check if an element (or collection) ".has()
" something. This is the programmatic equivalent to jQuery's selector filter, ":has()
".
This method will select all elements in the current collection that
contain at least one element that complies with the passed selector.
1
| jQuery( 'div' ).has( 'ul' ); |
:has()
"), but this method is still useful when you need to filter a collection programmatically.jQuery 1.4 also reveals the "
contains
" function under
the jQuery namespace. This is a low-level function that accepts two DOM
nodes. It'll return a boolean indicating whether the second element is
contained within the first element. E.g.
1
2
| jQuery.contains(document.documentElement, document.body); // Returns true - <body> is within <html> |
9. Unwrap Elements!
We've had the ".wrap()
" method for a while now. jQuery 1.4 adds the ".unwrap()
" method which does the complete opposite. If we assume the following DOM structure:
1
2
3
| < div > < p >Foo</ p > </ div > |
1
| jQuery( 'p' ).unwrap(); |
1
| < p >Foo</ p > |
10. Remove Elements Without Deleting Data
The new ".detach()
" method allows you to remove elements from the DOM, much like the ".remove()
"
method. The key difference with this new method is that it doesn't
destroy the data held by jQuery on that element. This includes data
added via ".data()
" and any event handlers added via jQuery's event system.This can be useful when you need to remove an element from the DOM, but you know you'll need to add it back at a later stage. Its event handlers and any other data will persist.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
| var foo = jQuery( '#foo' ); // Bind an important event handler foo.click( function (){ alert( 'Foo!' ); }); foo.detach(); // Remove it from the DOM // … do stuff foo.appendTo( 'body' ); // Add it back to the DOM foo.click(); // alerts "Foo!" |
11. index(…) Enhancements
jQuery 1.4 gives you two new ways to use the ".index()
"
method. Previously, you could only pass an element as its argument and
you'd expect a number to be returned indicating the index of that
element within the current collection.Passing no arguments now returns the index of an element amongst its siblings. So, assuming the following DOM structure:
1
2
3
4
5
6
7
8
9
| < ul > < li >Apple</ li > < li >Banana</ li > < li >Grape</ li > < li >Strawberry</ li > < li >Pear</ li > < li >Peach</ li > </ ul > |
1
2
3
| jQuery( 'li' ).click( function (){ alert( jQuery( this ).index() ); }); |
.index()
", doing so will give you the index of the current element amongst the collection produced from that selector.You should note that what's returned from this method is an integer, and it will return -1 if the selector/element passed cannot be found in the document.
12. DOM Manipulation Methods Accept Callbacks
Most of the DOM manipulation methods now support passing a function as the sole argument (or second, in the case of ".css()
" & ".attr()
").
This function will be run on every element in the collection to
determine what should be used as the real value for that method. The following methods have this capability:
- after
- before
- append
- prepend
- addClass
- toggleClass
- removeClass
- wrap
- wrapAll
- wrapInner
- val
- text
- replaceWith
- css
- attr
- html
this
" and its index via the first argument.
1
2
3
| jQuery( 'li' ).html( function (i){ return 'Index of this list item: ' + i; }); |
.html()
" or ".attr('href)
") you'll have access to the current value. E.g.
1
2
3
| jQuery( 'a' ).attr( 'href' , function (i, currentHref){ return currentHref + '?foo=bar' ; }); |
.css()
" and ".attr()
"
methods, you would pass the function as the second argument, since the
first would be used to name the property you wish to change:
1
2
3
| jQuery( 'li' ).css( 'color' , function (i, currentCssColor){ return i % 2 ? 'red' : 'blue' ; }); |
13. Determine the Type of Object
jQuery 1.4 adds two new helper functions (stored directly under the jQuery namespace) that help you determine what type of object you're dealing with.First, there's "
isEmptyObject
", this function returns a boolean indicating whether or not the the passed object is empty (devoid of properties - direct and inherited). Second, there's "isPlainObject
", which will return a boolean indicating whether the passed object is a plain JavaScript object, that is, one created via "{}
" or "new Object()
".
1
2
3
4
5
6
| jQuery.isEmptyObject({}); // true jQuery.isEmptyObject({foo:1}); // false jQuery.isPlainObject({}); // true jQuery.isPlainObject(window); // false jQuery.isPlainObject(jQuery()); // false |
isPlainObject(…)
, isEmptyObject(…)
14. Closest(…) Enhancements
jQuery's ".closest()
" method now accepts an array of
selectors. This is useful when you want to traverse the ancestors of an
element, looking for (more than one) closest elements with certain
characteristics.In addition, it now accepts a context as the second argument, meaning that you can control just how far or how close you want the DOM traversed to. Both of these enhancements accommodate rare use cases but they are used internally to great effect!
Read more about
.closest(…)
15. New Events! focusIn and focusOut
As mentioned, to delegate the "focus" and "blur" events you must use these new events, called "focusin" and "focusout". These events allow you to take action when an element, or a descendant of an element, gains focus.
1
2
3
4
5
6
7
| jQuery( 'form' ) .focusin( function (){ jQuery( this ).addClass( 'focused' ); }); .focusout( function (){ jQuery( this ).removeClass( 'focused' ); }); |
You should also note that both of these events do not propagate ("bubble"); they are captured. This means that the outermost (ancestor) element will be triggered before the causal "target" element.