Federico Bond - tagged with jquery http://www.federicobond.com.ar/feed en-us http://blogs.law.harvard.edu/tech/rss Sweetcron federicobond+lifestream@gmail.com 14 Helpful jQuery Tricks, Notes, and Best Practices http://www.federicobond.com.ar/items/view/1160/14-helpful-jquery-tricks-notes-and-best-practices

If there is one bad thing about jQuery, it’s that the entry level is so amazingly low, that it tends to attract those who haven’t an ounce of JavaScript knowledge. Now, on one hand, this is fantastic. However, on the flip side, it also results in a smattering of, quite frankly, disgustingly bad code (some of which I wrote myself!).

But that’s okay; frighteningly poor code that would even make your grandmother gasp is a rite of passage. The key is to climb over the hill, and that’s what we’ll discuss in today’s tutorial.

  1. Methods Return the jQuery Object It’s important to remember that most methods will return the jQuery object. This is extremely helpful, and allows for the chaining functionality that we use so often.

$someDiv .attr('class', 'someClass') .hide() .html('new stuff');

Knowing that the jQuery object is always returned, we can use this to remove superfluous code at times. For example, consider the following code:

var someDiv = $('#someDiv'); someDiv.hide();

The reason why we “cache” the location of the someDiv element is to limit the number of times that we have to traverse the DOM for this element to once.

The code above is perfectly fine; however, you could just as easily combine the two lines into one, while achieving the same outcome.

var someDiv = $('#someDiv').hide();

This way, we still hide the someDiv element, but the method also, as we learned, returns the jQuery object — which is then referenced via the someDiv variable.

  1. The Find Selector

As long as your selectors aren’t ridiculously poor, jQuery does a fantastic job of optimizing them as best as possible, and you generally don’t need to worry too much about them. However, with that said, there are a handful of improvements you can make that will slightly improve your script’s performance.

One such solution is to use the find() method, when possible. The key is stray away from forcing jQuery to use its Sizzle engine, if it’s not necessary. Certainly, there will be times when this isn’t possible — and that’s okay; but, if you don’t require the extra overhead, don’t go looking for it.

// Fine in modern browsers, though Sizzle does begin "running" $('#someDiv p.someClass').hide();

// Better for all browsers, and Sizzle never inits. $('#someDiv').find('p.someClass').hide();

The latest modern browsers have support for QuerySelectorAll, which allows you to pass CSS-like selectors, without the need for jQuery. jQuery itself checks for this function as well.

However, older browsers, namely IE6/IE7, understandably don’t provide support. What this means is that these more complicated selectors trigger jQuery’s full Sizzle engine, which, though brilliant, does come along with a bit more overhead.

Sizzle is a brilliant mass of code that I may never understand. However, in a sentence, it first takes your selector and turns it into an “array” composed of each component of your selector.

// Rough idea of how it works ['#someDiv, 'p'];

It then, from right to left, begins deciphering each item with regular expressions. What this also means is that the right-most part of your selector should be as specific as possible — for instance, an id or tag name. Bottom line, when possible:

Keep your selectors simple Utilize the find() method. This way, rather than using Sizzle, we can continue using the browser’s native functions. When using Sizzle, optimize the right-most part of your selector as much as possible.

Context Instead? It’s also possible to add a context to your selectors, such as:

$('.someElements, '#someContainer').hide();

This code directs jQuery to wrap a collection of all the elements with a class of someElements — that are children of someContainer — within jQuery. Using a context is a helpful way to limit DOM traversal, though, behind the scenes, jQuery is using the find method instead.

$('#someContainer') .find('.someElements') .hide();

Proof

// HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return jQuery( context ).find( selector ); }

  1. Don’t Abuse $(this)

Without knowing about the various DOM properties and functions, it can be easy to abuse the jQuery object needlessly. For instance:

$('#someAnchor').click(function() { // Bleh alert( $(this).attr('href') ); });

If our only need of the jQuery object is to access the anchor tag’s href attribute, this is wasteful. Better to stick with “raw” JavaScript.

$('#someAnchor').click(function() { alert( this.href ); });

Multiple jQuery Objects

Even worse is the process of repeatedly querying the DOM and creating multiple jQuery objects.

$('#elem').hide(); $('#elem').html('bla'); $('#elem').otherStuff();

Hopefully, you’re already aware of how inefficient this code is. If not, that’s okay; we’re all learning. The answer is to either implement chaining, or to “cache” the location of #elem.

// This works better $('#elem') .hide() .html('bla') .otherStuff();

// Or this, if you prefer for some reason. var elem = $('#elem'); elem.hide(); elem.html('bla'); elem.otherStuff();

  1. jQuery’s Shorthand Ready Method

Listening for when the document is ready to be manipulated is laughably simple with jQuery.

$(document).ready(function() { // let's get up in heeya });

Though, it’s very possible that you might have come across a different, more confusing wrapping function.

$(function() { // let's get up in heeya });

Though the latter is somewhat less readable, the two snippets above are identical. Don’t believe me? Just check the jQuery source.

// HANDLE: $(function) // Shortcut for document ready if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); }

rootjQuery is simply a reference to the root jQuery(document). When you pass a selector to the jQuery function, it’ll determine what type of selector you passed: string, tag, id, function, etc. If a function was passed, jQuery will then call its ready() method, and pass your anonymous function as the selector.

  1. Keep your Code Safe

If developing code for distribution, it’s always important to compensate for any possible name clashing. What would happen if some script, imported after yours, also had a $ function? Bad stuff!

The answer is to either call jQuery’s noConflict(), or to store your code within a self-invoking anonymous function, and then pass jQuery to it. Method 1: NoConflict

var j = jQuery.noConflict(); // Now, instead of $, we use j. j('#someDiv').hide();

// The line below will reference some other library's $ function. $('someDiv').style.display = 'none';

Method 2: Passing jQuery

(function($) { // Within this function, $ will always refer to jQuery })(jQuery);

The final parens at the bottom call the function automatically – function(){}(). However, when we call the function, we also pass jQuery, which is then represented by $.
Method 3: Passing $ via the Ready Method

jQuery(document).ready(function($) { // $ refers to jQuery });

// $ is either undefined, or refers to some other library's function.

  1. Be Smart

Remember – jQuery is just JavaScript. Don’t assume that it has the capacity to compensate for your bad coding.

This means that, just as we must optimize things such as JavaScript for statements, the same is true for jQuery’s each method. And why wouldn’t we? It’s just a helper method, which then creates a for statement behind the scenes.

// jQuery's each method source each: function( object, callback, args ) { var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction(object);

if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } }

// A special, fast, case for the most common use of each } else { if ( isObj ) { for ( name in object ) { if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} } }

return object; }

Awful

someDivs.each(function() { $('#anotherDiv')[0][removed] += $(this).text(); });

Searches for anotherDiv for each iteration Grabs the innerHTML property twice Creates a new jQuery object, all to access the text of the element.

Better

var someDivs = $('#container').find('.someDivs'), contents = [];

someDivs.each(function() { contents.push( this[removed] ); }); $('#anotherDiv').html( contents.join('') );

This way, within the each (for) method, the only task we're performing is adding a new key to an array…as opposed to querying the DOM, grabbing the innerHTML property of the element twice, etc. This tip is more JavaScript-based in general, rather than jQuery specific. The point is to remember that jQuery doesn't compensate for poor coding. Document Fragments

While we're at it, another option for these sorts of situations is to use document fragments.

var someUls = $('#container').find('.someUls'), frag = document.createDocumentFragment(), li;

someUls.each(function() { li = document.createElement('li'); li.appendChild( document.createTextNode(this[removed]) ); frag.appendChild(li); });

$('#anotherUl')[0].appendChild( frag );

The key here is that there are multiple ways to accomplish simple tasks like this, and each have their own performance benefits from browser to browser. The more you stick with jQuery and learn JavaScript, you also might find that you refer to JavaScript's native properties and methods more often. And, if so, that's fantastic! jQuery provides an amazing level of abstraction that you should take advantage of, but this doesn't mean that you're forced into using its methods. For example, in the fragment example above, we use jQuery's each method. If you prefer to use a for or while statement instead, that's okay too!

With all that said, keep in mind that the jQuery team have heavily optimized this library. The debates about jQuery's each() vs. the native for statement are silly and trivial. If you are using jQuery in your project, save time and use their helper methods. That's what they're there for!

  1. AJAX Methods

If you're just now beginning to dig into jQuery, the various AJAX methods that it makes available to us might come across as a bit daunting; though they needn't. In fact, most of them are simply helper methods, which route directly to $.ajax.

get getJSON post ajax

As an example, let's review getJSON, which allows us to fetch JSON.

$.getJSON('path/to/json', function(results) { // callback // results contains the returned data object });

Behind the scenes, this method first calls $.get.

getJSON: function( url, data, callback ) { return jQuery.get(url, data, callback, "json"); }

$.get then compiles the passed data, and, again, calls the "master" (of sorts) $.ajax method.

get: function( url, data, callback, type ) { // shift arguments if data argument was omited if ( jQuery.isFunction( data ) ) { type = type || callback; callback = data; data = null; }

return jQuery.ajax({ type: "GET", url: url, data: data, success: callback, dataType: type }); }

Finally, $.ajax performs a massive amount of work to allow us the ability to successfully make asynchronous requests across all browsers!

What this means is that you can just as well use the $.ajax method directly and exclusively for all your AJAX requests. The other methods are simply helper methods that end up doing this anyway. So, if you want, cut out the middle man. It's not a significant issue either way.

Just Dandy

$.getJSON('path/to/json', function(results) { // callback // results contains the returned data object });

Microscopically More Efficient

$.ajax({ type: 'GET', url : 'path/to/json', data : yourData, dataType : 'json', success : function( results ) { console.log('success'); }) });

  1. Accessing Native Properties and Methods

So you've learned a bit of JavaScript, and have learned that, for instance, on anchor tags, you can access attribute values directly:

var anchor = document.getElementById('someAnchor'); //anchor.id // anchor.href // anchor.title // .etc

The only problem is that this doesn't seem to work when you reference the DOM elements with jQuery, right? Well of course not. Won't Work

// Fails var href = $('#someAnchor').href;

So, should you need to access the href attribute (or any other native property or method for that matter), you have a handful of options.

// OPTION 1 - Use jQuery var href = $('#someAnchor').attr('href');

// OPTION 2 - Access the DOM element var href = $('#someAnchor')[0].href;

// OPTION 3 - Use jQuery's get method var href = $('#someAnchor').get(0).href;

// OPTION 3b - Don't pass an index to get anchorsArray = $('.someAnchors').get(); var thirdHref = anchorsArray[2].href;

The get method is particularly helpful, as it can translate your jQuery collection into an array.

  1. Detect AJAX Requests with PHP

Certainly, for the huge majority of our projects, we can't only rely on JavaScript for things like validation, or AJAX requests. What happens when JavaScript is turned off? For this very reason, a common technique is to detect whether an AJAX request has been made with your server-side language of choice.

jQuery makes this ridiculously simple, by setting a header from within the $.ajax method.

// Set header so the called script knows that it's an XMLHttpRequest // Only send the header if it's not a remote XHR if ( !remote ) { xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); }

With this header set, we can now use PHP (or any other language) to check for this header, and proceed accordingly. For this, we check the value of $_SERVER['HTTP_X_REQUESTED_WITH']. Wrapper

function isXhr() { return $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest'; }

  1. jQuery and $

Ever wonder why/how you can use jQuery and $ interchangeably? To find your answer, view the jQuery source, and scroll to the very bottom. There, you'll see:

window.jQuery = window.$ = jQuery;

The entire jQuery script is, of course, wrapped within a self-executing function, which allows the script to limit the number of global variables as much as possible. What this also means, though, is that the jQuery object is not available outside of the wrapping anonymous function. To fix this, jQuery is exposed to the global window object, and, in the process, an alias - $ - is also created.

  1. Conditionally Loading jQuery

HTML5 Boilerplate offers a nifty one-liner that will load a local copy of jQuery if, for some odd reason, your chosen CDN is down.

<!-- Grab Google CDN jQuery. fall back to local if necessary --> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script>!window.jQuery && [removed]('<script src="js/jquery-1.4.2.min.js"><\/script>')</script>

To "phrase" the code above: if window.jQuery is undefined, there must have been a problem downloading the script from the CDN. In that case, proceed to the right side of the && operator, and insert a script linking to a local version of jQuery.

  1. jQuery Filters

Premium Members: Download this Video ( Must be logged in) Subscribe to our YouTube page to watch all of the video tutorials!

<script> $('p:first').data('info', 'value'); // populates $'s data object to have something to work with

$.extend( jQuery.expr[":"], { block: function(elem) { return $(elem).css("display") === "block"; },

hasData : function(elem) { return !$.isEmptyObject( $(elem).data() ); } } );

$("p:hasData").text("has data"); // grabs paras that have data attached $("p:block").text("are block level"); // grabs only paragraphs that have a display of "block" </script>

Note: jQuery.expr[':'] is simply an alias for jQuery.expr.filters.

  1. A Single Hover Function As of jQuery 1.4, we can now pass only a single function to the hover method. Before, both the in and out methods were required. Before

$('#someElement').hover(function() { // mouseover }, function() { // mouseout });

Now

$('#someElement').hover(function() { // the toggle() method can be used here, if applicable });

Note that this isn't an old vs. new deal. Many times, you'll still need to pass two functions to hover, and that's perfectly acceptable. However, if you only need to toggle some element (or something like that), passing a single anonymous function will save a handful of characters or so!

  1. Passing an Attribute Object

As of jQuery 1.4, we can now pass an object as the second parameter of the jQuery function. This is helpful when we need to insert new elements into the DOM. For example:

Before

$('<a />') .attr({ id : 'someId', class : 'someClass' href : 'somePath.html' });

After

$('</a>', { id : 'someId', class : 'someClass' href : 'somePath.html' });

Not only does this save a few characters, but it also makes for cleaner code. In addition to element attributes, we can even pass jQuery specific attributes and events, like click or text.

Thanks for reading!

]]>
Fri, 10 Sep 2010 18:25:25 -0700 http://www.federicobond.com.ar/items/view/1160/14-helpful-jquery-tricks-notes-and-best-practices
14 Helpful jQuery Tricks, Notes, and Best Practices http://www.federicobond.com.ar/items/view/1221/14-helpful-jquery-tricks-notes-and-best-practices

If there is one bad thing about jQuery, it’s that the entry level is so amazingly low, that it tends to attract those who haven’t an ounce of JavaScript knowledge. Now, on one hand, this is fantastic. However, on the flip side, it also results in a smattering of, quite frankly, disgustingly bad code (some of which I wrote myself!).

But that’s okay; frighteningly poor code that would even make your grandmother gasp is a rite of passage. The key is to climb over the hill, and that’s what we’ll discuss in today’s tutorial.

  1. Methods Return the jQuery Object It’s important to remember that most methods will return the jQuery object. This is extremely helpful, and allows for the chaining functionality that we use so often.

$someDiv .attr('class', 'someClass') .hide() .html('new stuff');

Knowing that the jQuery object is always returned, we can use this to remove superfluous code at times. For example, consider the following code:

var someDiv = $('#someDiv'); someDiv.hide();

The reason why we “cache” the location of the someDiv element is to limit the number of times that we have to traverse the DOM for this element to once.

The code above is perfectly fine; however, you could just as easily combine the two lines into one, while achieving the same outcome.

var someDiv = $('#someDiv').hide();

This way, we still hide the someDiv element, but the method also, as we learned, returns the jQuery object — which is then referenced via the someDiv variable.

  1. The Find Selector

As long as your selectors aren’t ridiculously poor, jQuery does a fantastic job of optimizing them as best as possible, and you generally don’t need to worry too much about them. However, with that said, there are a handful of improvements you can make that will slightly improve your script’s performance.

One such solution is to use the find() method, when possible. The key is stray away from forcing jQuery to use its Sizzle engine, if it’s not necessary. Certainly, there will be times when this isn’t possible — and that’s okay; but, if you don’t require the extra overhead, don’t go looking for it.

// Fine in modern browsers, though Sizzle does begin "running" $('#someDiv p.someClass').hide();

// Better for all browsers, and Sizzle never inits. $('#someDiv').find('p.someClass').hide();

The latest modern browsers have support for QuerySelectorAll, which allows you to pass CSS-like selectors, without the need for jQuery. jQuery itself checks for this function as well.

However, older browsers, namely IE6/IE7, understandably don’t provide support. What this means is that these more complicated selectors trigger jQuery’s full Sizzle engine, which, though brilliant, does come along with a bit more overhead.

Sizzle is a brilliant mass of code that I may never understand. However, in a sentence, it first takes your selector and turns it into an “array” composed of each component of your selector.

// Rough idea of how it works ['#someDiv, 'p'];

It then, from right to left, begins deciphering each item with regular expressions. What this also means is that the right-most part of your selector should be as specific as possible — for instance, an id or tag name. Bottom line, when possible:

Keep your selectors simple Utilize the find() method. This way, rather than using Sizzle, we can continue using the browser’s native functions. When using Sizzle, optimize the right-most part of your selector as much as possible.

Context Instead? It’s also possible to add a context to your selectors, such as:

$('.someElements', '#someContainer').hide();

This code directs jQuery to wrap a collection of all the elements with a class of someElements — that are children of someContainer — within jQuery. Using a context is a helpful way to limit DOM traversal, though, behind the scenes, jQuery is using the find method instead.

$('#someContainer') .find('.someElements') .hide();

Proof

// HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return jQuery( context ).find( selector ); }

  1. Don’t Abuse $(this)

Without knowing about the various DOM properties and functions, it can be easy to abuse the jQuery object needlessly. For instance:

$('#someAnchor').click(function() { // Bleh alert( $(this).attr('id') ); });

If our only need of the jQuery object is to access the anchor tag’s id attribute, this is wasteful. Better to stick with “raw” JavaScript.

$('#someAnchor').click(function() { alert( this.id ); });

Please note that there are three attributes that should always be accessed, via jQuery: “src,” “href,” and “style.” These attributes require the use of getAttribute in older versions of IE.

Proof

// jQuery Source var rspecialurl = /href|src|style/; // ... var special = rspecialurl.test( name ); // ... var attr = !jQuery.support.hrefNormalized && notxml && special ? // Some attributes require a special call on IE elem.getAttribute( name, 2 ) : elem.getAttribute( name );

Multiple jQuery Objects

Even worse is the process of repeatedly querying the DOM and creating multiple jQuery objects.

$('#elem').hide(); $('#elem').html('bla'); $('#elem').otherStuff();

Hopefully, you’re already aware of how inefficient this code is. If not, that’s okay; we’re all learning. The answer is to either implement chaining, or to “cache” the location of #elem.

// This works better $('#elem') .hide() .html('bla') .otherStuff();

// Or this, if you prefer for some reason. var elem = $('#elem'); elem.hide(); elem.html('bla'); elem.otherStuff();

  1. jQuery’s Shorthand Ready Method

Listening for when the document is ready to be manipulated is laughably simple with jQuery.

$(document).ready(function() { // let's get up in heeya });

Though, it’s very possible that you might have come across a different, more confusing wrapping function.

$(function() { // let's get up in heeya });

Though the latter is somewhat less readable, the two snippets above are identical. Don’t believe me? Just check the jQuery source.

// HANDLE: $(function) // Shortcut for document ready if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); }

rootjQuery is simply a reference to the root jQuery(document). When you pass a selector to the jQuery function, it’ll determine what type of selector you passed: string, tag, id, function, etc. If a function was passed, jQuery will then call its ready() method, and pass your anonymous function as the selector.

  1. Keep your Code Safe

If developing code for distribution, it’s always important to compensate for any possible name clashing. What would happen if some script, imported after yours, also had a $ function? Bad stuff!

The answer is to either call jQuery’s noConflict(), or to store your code within a self-invoking anonymous function, and then pass jQuery to it. Method 1: NoConflict

var j = jQuery.noConflict(); // Now, instead of $, we use j. j('#someDiv').hide();

// The line below will reference some other library's $ function. $('someDiv').style.display = 'none';

Be careful with this method, and try not to use it when distributing your code. It would really confuse the user of your script!
Method 2: Passing jQuery

(function($) { // Within this function, $ will always refer to jQuery })(jQuery);

The final parens at the bottom call the function automatically – function(){}(). However, when we call the function, we also pass jQuery, which is then represented by $.
Method 3: Passing $ via the Ready Method

jQuery(document).ready(function($) { // $ refers to jQuery });

// $ is either undefined, or refers to some other library's function.

  1. Be Smart

Remember – jQuery is just JavaScript. Don’t assume that it has the capacity to compensate for your bad coding.

This means that, just as we must optimize things such as JavaScript for statements, the same is true for jQuery’s each method. And why wouldn’t we? It’s just a helper method, which then creates a for statement behind the scenes.

// jQuery's each method source each: function( object, callback, args ) { var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction(object);

if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } }

// A special, fast, case for the most common use of each } else { if ( isObj ) { for ( name in object ) { if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} } }

return object; }

Awful

someDivs.each(function() { $('#anotherDiv')[0][removed] += $(this).text(); });

Searches for anotherDiv for each iteration Grabs the innerHTML property twice Creates a new jQuery object, all to access the text of the element.

Better

var someDivs = $('#container').find('.someDivs'), contents = [];

someDivs.each(function() { contents.push( this[removed] ); }); $('#anotherDiv').html( contents.join('') );

This way, within the each (for) method, the only task we're performing is adding a new key to an array…as opposed to querying the DOM, grabbing the innerHTML property of the element twice, etc. This tip is more JavaScript-based in general, rather than jQuery specific. The point is to remember that jQuery doesn't compensate for poor coding. Document Fragments

While we're at it, another option for these sorts of situations is to use document fragments.

var someUls = $('#container').find('.someUls'), frag = document.createDocumentFragment(), li;

someUls.each(function() { li = document.createElement('li'); li.appendChild( document.createTextNode(this[removed]) ); frag.appendChild(li); });

$('#anotherUl')[0].appendChild( frag );

The key here is that there are multiple ways to accomplish simple tasks like this, and each have their own performance benefits from browser to browser. The more you stick with jQuery and learn JavaScript, you also might find that you refer to JavaScript's native properties and methods more often. And, if so, that's fantastic! jQuery provides an amazing level of abstraction that you should take advantage of, but this doesn't mean that you're forced into using its methods. For example, in the fragment example above, we use jQuery's each method. If you prefer to use a for or while statement instead, that's okay too!

With all that said, keep in mind that the jQuery team have heavily optimized this library. The debates about jQuery's each() vs. the native for statement are silly and trivial. If you are using jQuery in your project, save time and use their helper methods. That's what they're there for!

  1. AJAX Methods

If you're just now beginning to dig into jQuery, the various AJAX methods that it makes available to us might come across as a bit daunting; though they needn't. In fact, most of them are simply helper methods, which route directly to $.ajax.

get getJSON post ajax

As an example, let's review getJSON, which allows us to fetch JSON.

$.getJSON('path/to/json', function(results) { // callback // results contains the returned data object });

Behind the scenes, this method first calls $.get.

getJSON: function( url, data, callback ) { return jQuery.get(url, data, callback, "json"); }

$.get then compiles the passed data, and, again, calls the "master" (of sorts) $.ajax method.

get: function( url, data, callback, type ) { // shift arguments if data argument was omited if ( jQuery.isFunction( data ) ) { type = type || callback; callback = data; data = null; }

return jQuery.ajax({ type: "GET", url: url, data: data, success: callback, dataType: type }); }

Finally, $.ajax performs a massive amount of work to allow us the ability to successfully make asynchronous requests across all browsers!

What this means is that you can just as well use the $.ajax method directly and exclusively for all your AJAX requests. The other methods are simply helper methods that end up doing this anyway. So, if you want, cut out the middle man. It's not a significant issue either way.

Just Dandy

$.getJSON('path/to/json', function(results) { // callback // results contains the returned data object });

Microscopically More Efficient

$.ajax({ type: 'GET', url : 'path/to/json', data : yourData, dataType : 'json', success : function( results ) { console.log('success'); }) });

  1. Accessing Native Properties and Methods

So you've learned a bit of JavaScript, and have learned that, for instance, on anchor tags, you can access attribute values directly:

var anchor = document.getElementById('someAnchor'); //anchor.id // anchor.href // anchor.title // .etc

The only problem is that this doesn't seem to work when you reference the DOM elements with jQuery, right? Well of course not. Won't Work

// Fails var id = $('#someAnchor').id;

So, should you need to access the href attribute (or any other native property or method for that matter), you have a handful of options.

// OPTION 1 - Use jQuery var id = $('#someAnchor').attr('id');

// OPTION 2 - Access the DOM element var id = $('#someAnchor')[0].id;

// OPTION 3 - Use jQuery's get method var id = $('#someAnchor').get(0).id;

// OPTION 3b - Don't pass an index to get anchorsArray = $('.someAnchors').get(); var thirdId = anchorsArray[2].id;

The get method is particularly helpful, as it can translate your jQuery collection into an array.

  1. Detect AJAX Requests with PHP

Certainly, for the huge majority of our projects, we can't only rely on JavaScript for things like validation, or AJAX requests. What happens when JavaScript is turned off? For this very reason, a common technique is to detect whether an AJAX request has been made with your server-side language of choice.

jQuery makes this ridiculously simple, by setting a header from within the $.ajax method.

// Set header so the called script knows that it's an XMLHttpRequest // Only send the header if it's not a remote XHR if ( !remote ) { xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); }

With this header set, we can now use PHP (or any other language) to check for this header, and proceed accordingly. For this, we check the value of $_SERVER['HTTP_X_REQUESTED_WITH']. Wrapper

function isXhr() { return $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest'; }

  1. jQuery and $

Ever wonder why/how you can use jQuery and $ interchangeably? To find your answer, view the jQuery source, and scroll to the very bottom. There, you'll see:

window.jQuery = window.$ = jQuery;

The entire jQuery script is, of course, wrapped within a self-executing function, which allows the script to limit the number of global variables as much as possible. What this also means, though, is that the jQuery object is not available outside of the wrapping anonymous function. To fix this, jQuery is exposed to the global window object, and, in the process, an alias - $ - is also created.

  1. Conditionally Loading jQuery

HTML5 Boilerplate offers a nifty one-liner that will load a local copy of jQuery if, for some odd reason, your chosen CDN is down.

<!-- Grab Google CDN jQuery. fall back to local if necessary --> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script>!window.jQuery && [removed]('<script src="js/jquery-1.4.2.min.js"><\/script>')</script>

To "phrase" the code above: if window.jQuery is undefined, there must have been a problem downloading the script from the CDN. In that case, proceed to the right side of the && operator, and insert a script linking to a local version of jQuery.

  1. jQuery Filters

Premium Members: Download this Video ( Must be logged in) Subscribe to our YouTube page to watch all of the video tutorials!

<script> $('p:first').data('info', 'value'); // populates $'s data object to have something to work with

$.extend( jQuery.expr[":"], { block: function(elem) { return $(elem).css("display") === "block"; },

hasData : function(elem) { return !$.isEmptyObject( $(elem).data() ); } } );

$("p:hasData").text("has data"); // grabs paras that have data attached $("p:block").text("are block level"); // grabs only paragraphs that have a display of "block" </script>

Note: jQuery.expr[':'] is simply an alias for jQuery.expr.filters.

  1. A Single Hover Function As of jQuery 1.4, we can now pass only a single function to the hover method. Before, both the in and out methods were required. Before

$('#someElement').hover(function() { // mouseover }, function() { // mouseout });

Now

$('#someElement').hover(function() { // the toggle() method can be used here, if applicable });

Note that this isn't an old vs. new deal. Many times, you'll still need to pass two functions to hover, and that's perfectly acceptable. However, if you only need to toggle some element (or something like that), passing a single anonymous function will save a handful of characters or so!

  1. Passing an Attribute Object

As of jQuery 1.4, we can now pass an object as the second parameter of the jQuery function. This is helpful when we need to insert new elements into the DOM. For example:

Before

$('<a />') .attr({ id : 'someId', className : 'someClass', href : 'somePath.html' });

After

$('</a>', { id : 'someId', className : 'someClass', href : 'somePath.html' });

Not only does this save a few characters, but it also makes for cleaner code. In addition to element attributes, we can even pass jQuery specific attributes and events, like click or text.

Thanks for reading!

]]>
Fri, 10 Sep 2010 18:25:00 -0700 http://www.federicobond.com.ar/items/view/1221/14-helpful-jquery-tricks-notes-and-best-practices
Quick Tip: Different Layouts for Different Widths http://www.federicobond.com.ar/items/view/664/quick-tip-different-layouts-for-different-widths

It’s becoming more and more common for web sites and applications to provide different layouts dependent upon the user’s window size, or resolution. This can be accomplished in a variety of ways, ranging from CSS to JavaScript solutions.In this video quick tip, we’ll learn how laughably simple it is to do this with a touch of jQuery, and the resize() method. By utilizing jQuery’s “resize()” method, we can easily listen for when the user changes the width of their browser window. function checkWindowSize() {

if ( $(window).width() > 1800 ) { $('body').addClass('large'); } else { $('body').removeClass('large'); }

}

$(window).resize(checkWindowSize); Then, subsequently, we target our desired CSS properties accordingly.

container {

width: 800px; height: 1000px; background: #e3e3e3; margin: auto; }

/* Change container size for larger windows. */ .large #container { width: 1000px; }

nav {

width: 100%; height: 100px; border-bottom: 1px solid white; background: #999999;

}

.large #nav { float: left; width: 200px; border-bottom: none; border-right: 1px solid white; height: 1000px; } Follow us on Twitter, or subscribe to the Nettuts+ RSS Feed for the best web development tutorials on the web.

]]>
Fri, 12 Feb 2010 11:21:47 -0800 http://www.federicobond.com.ar/items/view/664/quick-tip-different-layouts-for-different-widths
jQuery 1.4 Released: The 15 New Features you Must Know http://www.federicobond.com.ar/items/view/505/jquery-14-released-the-15-new-features-you-must-know

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.js1. 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: jQuery('<a/>', { id: 'foo', href: 'http://google.com', title: 'Become a Googler', rel: 'external', text: 'Go to Google!' }); You may have noticed the "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: jQuery('<div/>', { id: 'foo', css: { fontWeight: 700, color: 'green' }, click: function(){ alert('Foo has been clicked!'); } }); 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: jQuery('<div/>') .attr('id', 'foo') .css({ fontWeight: 700, color: 'green' }) .click(function(){ alert('Foo has been clicked!'); }); Read more about jQuery(…)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: <ul> <li>Apple</li> <li>Banana</li> <li>Grape</li>

&lt;li&gt;Strawberry&lt;/li&gt;
&lt;li&gt;Pear&lt;/li&gt;
&lt;li&gt;Peach&lt;/li&gt;

</ul> You want to select all of items after "Apple", but you want to stop once you reach "Strawberry". It couldn’t be simpler: jQuery('ul li:contains(Apple)').nextUntil(':contains(Pear)'); // Selects Banana, Grape, Strawberry Read more about: prevUntil, nextUntil, parentsUntil3. Binding Multiple Event HandlersInstead of chaining a bunch of event binding methods together, you can lump them all into the same call, like so: jQuery('#foo).bind({ click: function() { // do something }, mouseover: function() { // do something }, mouseout: function() { // do something } }) This also works with ".one()".Read more about .bind(…)4. Per-Property EasingInstead 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: jQuery('#foo').animate({ left: 500, top: [500, 'easeOutBounce'] }, 2000); See this code in action!You can also define per-property easing functions in the optional options object as property name-value pairs in the "specialEasing" object: jQuery('#foo').animate({ left: 500, top: 500 }, { duration: 2000, specialEasing: { top: 'easeOutBounce' } }); Editor’s Note – The author of this article, James Padolsey, is being modest. This new feature was his idea! Read more about per-property easing5. 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! jQuery('input').live('focusin', function(){ // do something with this }); 6. Controlling a Function’s ContextjQuery 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: var app = { config: { clickMessage: 'Hi!' }, clickHandler: function() { alert(this.config.clickMessage); } }; The "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: app.clickHandler(); // "Hi!" is alerted Let’s try binding it as an event handler: jQuery('a').bind('click', app.clickHandler);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 "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: jQuery('a').bind( 'click', jQuery.proxy(app, 'clickHandler') );Now whenever an anchor is clicked, “Hi!” will be alerted!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.Read more about jQuery.proxy7. Delay an Animation QueueYou 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. jQuery('#foo') .slideDown() // Slide down .delay(200) // Do nothing for 200 ms .fadeIn(); // Fade in 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 ".delay()".Read more about .delay(…)8. Check if an Element Has SomethingjQuery 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. jQuery('div').has('ul');That would select all DIV elements that contain UL elements. In this situation you’d probably just use the selector filter (":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. jQuery.contains(document.documentElement, document.body); // Returns true - <body> is within <html> Read more about: .has(…), jQuery.contains(…)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: <div> <p>Foo</p> </div> We can unwrap the paragraph element like so: jQuery('p').unwrap(); The resulting DOM structure would be: <p>Foo</p> Essentially, this method simply removes the parent of any element.Read more about .unwrap(…)10. Remove Elements Without Deleting DataThe 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. 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!" Read more about .detach(…)11. index(…) EnhancementsjQuery 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: <ul> <li>Apple</li> <li>Banana</li> <li>Grape</li>

&lt;li&gt;Strawberry&lt;/li&gt;
&lt;li&gt;Pear&lt;/li&gt;
&lt;li&gt;Peach&lt;/li&gt;

</ul> 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('li').click(function(){ alert( jQuery(this).index() ); }); jQuery 1.4 also allows you to specify a selector as the first argument to ".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.Read more about .index(…)12. DOM Manipulation Methods Accept CallbacksMost 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:afterbeforeappendprependaddClasstoggleClassremoveClasswrapwrapAllwrapInnervaltextreplaceWithcssattrhtmlWithin the callback function, you’ll have access to the current element in the collection via "this" and its index via the first argument. jQuery('li').html(function(i){ return 'Index of this list item: ' + i; }); Also, with some of the above methods you’ll also get a second argument. If you’re calling a setter method (like ".html()" or ".attr('href)") you’ll have access to the current value. E.g. jQuery('a').attr('href', function(i, currentHref){ return currentHref + '?foo=bar'; }); As you can see, with the ".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: jQuery('li').css('color', function(i, currentCssColor){ return i % 2 ? 'red' : 'blue'; }); 13. Determine the Type of ObjectjQuery 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()". jQuery.isEmptyObject({}); // true jQuery.isEmptyObject({foo:1}); // false

jQuery.isPlainObject({}); // true jQuery.isPlainObject(window); // false jQuery.isPlainObject(jQuery()); // false Read more about: isPlainObject(…), isEmptyObject(…)14. Closest(…) EnhancementsjQuery’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 focusOutAs 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. 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.Read more about the focusIn and focusOut events.Enjoy jQuery 1.4, the most anticipated, most feature-rich, best performing release of jQuery yet!Well, that’s it! I’ve tried to cover the changes which I think will have an impact on you!If you haven’t already, you should check out the "14 days of jQuery", an awesome online event marking the release of jQuery 1.4, and jQuery’s fourth birthday!And don’t forget to checkout the new API documentation!Write a Plus TutorialDid you know that you can earn up to $600 for writing a PLUS tutorial and/or screencast for us? We’re looking for in depth and well-written tutorials on HTML, CSS, PHP, and JavaScript. If you’re of the ability, please contact Jeffrey at nettuts@tutsplus.com.Please note that actual compensation will be dependent upon the quality of the final tutorial and screencast.Follow us on Twitter, or subscribe to the Nettuts+ RSS Feed for the best web development tutorials on the web.

]]>
Thu, 14 Jan 2010 11:37:16 -0800 http://www.federicobond.com.ar/items/view/505/jquery-14-released-the-15-new-features-you-must-know
Code Snippets http://www.federicobond.com.ar/items/view/202/code-snippets ]]> Fri, 30 Oct 2009 16:51:00 -0700 http://www.federicobond.com.ar/items/view/202/code-snippets