From 44fc87f66ca54278e37f15885a80c2407036df57 Mon Sep 17 00:00:00 2001 From: jaubourg Date: Thu, 13 Jan 2011 17:01:25 +0100 Subject: [PATCH] Fixes #4964. Adds a statusCode object together with a new statusCode method on the jXHR object (deferred behaviour). They accept a map of statusCode/callback(s). Callbacks are fired when the status code of the response correponds to the key (as a success or an error callback depending on how the request completed). Unit tests added. --- src/ajax.js | 27 ++++++++++++++++++ test/unit/ajax.js | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/src/ajax.js b/src/ajax.js index c2dc3e404..a2ef4397b 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -265,6 +265,8 @@ jQuery.extend({ // Deferreds deferred = jQuery.Deferred(), completeDeferred = jQuery._Deferred(), + // Status-dependent callbacks + statusCode = s.statusCode || {}, // Headers (they are sent all at once) requestHeaders = {}, // Response headers @@ -520,6 +522,9 @@ jQuery.extend({ deferred.fireReject( callbackContext , [ jXHR , statusText , error ] ); } + // Status-dependent callbacks + jXHR.statusCode( statusCode ); + if ( s.global ) { globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ) , [ jXHR , s , isSuccess ? success : error ] ); @@ -543,6 +548,28 @@ jQuery.extend({ jXHR.error = jXHR.fail; jXHR.complete = completeDeferred.done; + // Status-dependent callbacks + jXHR.statusCode = function( map ) { + if ( map ) { + var resolved = jXHR.isResolved(), + tmp; + if ( resolved || jXHR.isRejected() ) { + tmp = map[ jXHR.status ]; + if ( tmp ) { + if ( map === statusCode ) { + delete statusCode[ jXHR.status ]; + } + jXHR[ resolved ? "done" : "fail" ]( tmp ); + } + } else { + for( tmp in map ) { + statusCode[ tmp ] = [ statusCode[ tmp ] , map[ tmp ] ]; + } + } + } + return this; + }; + // Remove hash character (#7531: and string promotion) s.url = ( "" + s.url ).replace( rhash , "" ); diff --git a/test/unit/ajax.js b/test/unit/ajax.js index 10c2e7183..f5b71da39 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -1915,6 +1915,76 @@ test( "jQuery.ajax - Location object as url (#7531)", 1, function () { ok( success, "document.location did not generate exception" ); }); +test( "jQuery.ajax - statusCode" , function() { + + var count = 10; + + expect( 16 ); + stop(); + + function countComplete() { + if ( ! --count ) { + start(); + } + } + + function createStatusCodes( name , isSuccess ) { + name = "Test " + name + " " + ( isSuccess ? "success" : "error" ); + return { + 200: function() { + ok( isSuccess , name ); + }, + 404: function() { + ok( ! isSuccess , name ); + } + } + } + + jQuery.each( { + "data/name.html": true, + "data/someFileThatDoesNotExist.html": false + } , function( uri , isSuccess ) { + + jQuery.ajax( url( uri ) , { + statusCode: createStatusCodes( "in options" , isSuccess ), + complete: countComplete + }); + + jQuery.ajax( url( uri ) , { + complete: countComplete + }).statusCode( createStatusCodes( "immediately with method" , isSuccess ) ); + + jQuery.ajax( url( uri ) , { + complete: function(jXHR) { + jXHR.statusCode( createStatusCodes( "on complete" , isSuccess ) ); + countComplete(); + } + }); + + jQuery.ajax( url( uri ) , { + complete: function(jXHR) { + setTimeout( function() { + jXHR.statusCode( createStatusCodes( "very late binding" , isSuccess ) ); + countComplete(); + } , 100 ); + } + }); + + jQuery.ajax( url( uri ) , { + statusCode: createStatusCodes( "all (options)" , isSuccess ), + complete: function(jXHR) { + jXHR.statusCode( createStatusCodes( "all (on complete)" , isSuccess ) ); + setTimeout( function() { + jXHR.statusCode( createStatusCodes( "all (very late binding)" , isSuccess ) ); + countComplete(); + } , 100 ); + } + }).statusCode( createStatusCodes( "all (immediately with method)" , isSuccess ) ); + + }); + +}); + } //} \ No newline at end of file