Posted by: mashuphowto | mars 24, 2008

Json for jQuery

Michael Geary | Wed, 2006-01-25 00:10

Update 2007-09-13: As of version 1.2, the jQuery core now supports cross-domain JSONP downloads as part of the native Ajax support. I suggest you use this support instead of the plugin.jQuery is a nifty new JavaScript library by John Resig. It features a $() function like the one in Prototype.js, but beefed up with CSS and XPath selectors, and with the ability to chain methods to do interesting things with concise code.

Unlike Prototype, jQuery doesn’t mess around with built-in JavaScript objects. It’s new—too new to have a version number!—but I’ve been writing some code with it and enjoying it.

jQuery provides an easy way to write plugin methods to extend the $ function. For you JSON fans out there, here is a JSON plugin for jQuery which lets you write code like this:

function doJson( json ) {

  // handle the json object here

}
$(‘#test’).json( ‘http://example.com/json-test?jsonp={callback}’, doJson );

You can of course use an anonymous function if you prefer:

var url = ‘http://example.com/json-test?jsonp={callback}’;

$(‘#test’).json( url, function(json) {

  // handle the json object here

});

Or, using jQuery’s method chaining, you can combine calls like this code which displays a “Loading…” message when it starts loading the JSON resource:

$(‘#test’).html( ‘Loading…’ ).json( ‘http://example.com/json-test?jsonp={callback}’, doJson );

To install the plugin, simply paste this code into a .js file and load it after loading jquery.js:

// JSON for jQuery by Michael Geary

// See http://mg.to/2006/01/25/json-for-jquery

// Free beer and free speech. Enjoy!
$.json = { callbacks: {} };
$.fn.json = function( url, callback ) {

    var _$_ = this;

    load( url.replace( /{callback}/, name(callback) ) );

    return this;

    function name( callback ) {

        var id = (new Date).getTime();

        var name = ‘json_’ + id;

        var cb = $.json.callbacks[id] = function( json ) {

            delete $.json.callbacks[id];

            eval( ‘delete ‘ + name );

            _$_.each( function() { callback(json); } );

        };

        eval( name + ‘ = cb’ );

        return name;

    }

    function load( url ) {

        var script = document.createElement( ’script’ );

        script.type = ‘text/javascript’;

        script.src = url;

        $(‘head’,document).append( script );

    }

};

This adds a json() method to the $ function. The first argument is the URL to the JSON resource, with the text {callback} wherever the JSON callback method should be provided. In a JSONP URL, you would use jsonp={callback}; in a Yahoo! JSON URL you would use format=json&callback={callback}.

The second argument is the callback function itself. When the JSON resource finishes loading, this function will be called with a single argument, the JSON object itself. Inside the callback function, this is a reference to the HTML element found by the $ function. (If $ found more than one element, the callback function is called for each of them.)

The callback function is required, so this code won’t work with plain JSON APIs like del.icio.us that don’t let you specify a callback function. This would be easy enough to fix; I didn’t need it for the code I was writing, and didn’t think of it until just now. :-)

The code goes to a bit of extra work to create both an array entry and a unique global name for each callback. The global name is what is substituted into the {callback} part of the URL. It uses this name instead of the array reference to ensure compatibility with any JSON APIs that don’t allow special characters in the callback name. In fact, in the current code the callbacks[] array entries are not really used, but I figured it could be handy to have an array of all outstanding callbacks.

Update: John Resig suggested a couple of improvements to the code, so it’s updated, simpler and better now.

Update 2: Code updated to include Stephen and Brent’s fixes from the comments.

Leave a response

Your response:

Catégories