X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fajax.js;h=187236576c439ab4da409eefe7a21e35042ff7aa;hb=328a86f9a0d3f0907cc950f7543e34cb3efbda3f;hp=63914d23a7aa876499b87be16ea6c1ccec1f0a40;hpb=9ab00a712fe3757f130dce8b42293c82a68c690e;p=jquery.git diff --git a/src/ajax.js b/src/ajax.js index 63914d2..1872365 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -199,6 +199,11 @@ jQuery.extend({ json: /json/ }, + responseFields: { + xml: "responseXML", + text: "responseText" + }, + // Prefilters // 1) They are useful to introduce custom dataTypes (see transport/jsonp for an example) // 2) These are called: @@ -231,53 +236,7 @@ jQuery.extend({ // Parse text as xml "text xml": jQuery.parseXML - }, - - // Utility function that handles dataType when response is received - // (for those transports that can give text or xml responses) - determineDataType: function( ct , text , xml ) { - - var s = this, - contents = s.contents, - type, - regexp, - dataTypes = s.dataTypes, - transportDataType = dataTypes[0], - response; - - // Auto (xml, json, script or text determined given headers) - if ( transportDataType === "*" ) { - - for ( type in contents ) { - if ( ( regexp = contents[ type ] ) && regexp.test( ct ) ) { - transportDataType = dataTypes[0] = type; - break; - } - } - } - - // xml and parsed as such - if ( transportDataType === "xml" && - xml && - xml.documentElement /* #4958 */ ) { - - response = xml; - - // Text response was provided - } else { - - response = text; - - // If it's not really text, defer to converters - if ( transportDataType !== "text" ) { - dataTypes.unshift( "text" ); - } - - } - - return response; } - }, ajaxPrefilter: function( a , b ) { @@ -291,18 +250,16 @@ jQuery.extend({ // Main method ajax: function( url , options ) { - // Handle varargs - if ( arguments.length === 1 ) { + // If options is not an object, + // we simulate pre-1.5 signature + if ( typeof( options ) !== "object" ) { options = url; - url = options ? options.url : undefined; + url = undefined; } // Force options to be an object options = options || {}; - // Get the url if provided separately - options.url = url || options.url; - var // Create the final options object s = jQuery.extend( true , {} , jQuery.ajaxSettings , options ), // jQuery lists @@ -390,7 +347,7 @@ jQuery.extend({ // Callback for when everything is done // It is defined here because jslint complains if it is declared // at the end of the function (which would be more logical and readable) - function done( status , statusText , response , headers) { + function done( status , statusText , responses , headers) { // Called once if ( state === 2 ) { @@ -401,7 +358,7 @@ jQuery.extend({ state = 2; // Dereference transport for early garbage collection - // (no matter how long the jXHR transport will be used + // (no matter how long the jXHR object will be used) transport = undefined; // Set readyState @@ -415,20 +372,94 @@ jQuery.extend({ clearTimeout(timeoutTimer); } - var // Reference url - url = s.url, - // and ifModified status - ifModified = s.ifModified, + var // Reference dataTypes, converters and responseFields + dataTypes = s.dataTypes, + converters = s.converters, + responseFields = s.responseFields, + responseField, - // Is it a success? - isSuccess = 0, + // Flag to mark as success + isSuccess, // Stored success success, // Stored error error, // To keep track of statusCode based callbacks - oldStatusCode; + oldStatusCode, + + // Actual response + response; + + // If we got responses: + // - find the right one + // - update dataTypes accordingly + // - set responseXXX accordingly too + if ( responses ) { + + var contents = s.contents, + transportDataType = dataTypes[0], + ct, + type, + finalDataType, + firstDataType; + + // Auto (xml, json, script or text determined given headers) + if ( transportDataType === "*" ) { + + // Remove all auto types + while( dataTypes[0] === "*" ) { + dataTypes.shift(); + } + transportDataTypes = dataTypes[0]; + + // Get content type + ct = jXHR.getResponseHeader( "content-type" ); + + // Check if it's a known type + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( ( transportDataType = type ) ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( transportDataType in responses ) { + finalDataType = transportDataType; + } else { + // Try convertible dataTypes + for ( type in responses ) { + if ( ! firstDataType ) { + firstDataType = type; + } + if ( ! transportDataType || converters[ type + " " + transportDataType ] ) { + finalDataType = type; + break; + } + } + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We get the corresponding response + // and add the dataType to the list if needed + if ( finalDataType ) { + response = responses[ finalDataType ]; + if ( finalDataType !== transportDataType ) { + dataTypes.unshift( finalDataType ); + } + } + + // Fill responseXXX fields + for( type in responseFields ) { + if ( type in responses ) { + jXHR[ responseFields[ type ] ] = responses[ type ]; + } + } + } // If successful, handle type chaining if ( status >= 200 && status < 300 || status === 304 ) { @@ -450,15 +481,12 @@ jQuery.extend({ // If not modified if ( status === 304 ) { - // Set the statusText accordingly statusText = "notmodified"; - // Mark as a success isSuccess = 1; // If we have data } else { - // Set the statusText accordingly statusText = "success"; // Chain data conversions and determine the final value @@ -466,6 +494,7 @@ jQuery.extend({ try { var i, + tmp, // Current dataType current, // Previous dataType @@ -476,15 +505,7 @@ jQuery.extend({ conv, // Conversion functions (when text is used in-between) conv1, - conv2, - // Local references to dataTypes & converters - dataTypes = s.dataTypes, - converters = s.converters, - // DataType to responseXXX field mapping - responses = { - "xml": "XML", - "text": "Text" - }; + conv2; // For each dataType in the chain for( i = 0 ; i < dataTypes.length ; i++ ) { @@ -493,11 +514,9 @@ jQuery.extend({ // If a responseXXX field for this dataType exists // and if it hasn't been set yet - if ( responses[ current ] ) { - // Set it - jXHR[ "response" + responses[ current ] ] = response; - // Mark it as set - responses[ current ] = 0; + responseField = responseFields[ current ]; + if ( responseField && ! ( responseField in jXHR ) ) { + jXHR[ responseField ] = response; } // If this is not the first element @@ -506,26 +525,31 @@ jQuery.extend({ // Get the dataType to convert from prev = dataTypes[ i - 1 ]; - // If no catch-all and dataTypes are actually different + // If no auto and dataTypes are actually different if ( prev !== "*" && current !== "*" && prev !== current ) { // Get the converter conversion = prev + " " + current; conv = converters[ conversion ] || converters[ "* " + current ]; - conv1 = conv2 = 0; - - // If there is no direct converter and none of the dataTypes is text - if ( ! conv && prev !== "text" && current !== "text" ) { - // Try with text in-between - conv1 = converters[ prev + " text" ] || converters[ "* text" ]; - conv2 = converters[ "text " + current ]; - // Revert back to a single converter - // if one of the converter is an equivalence - if ( conv1 === true ) { - conv = conv2; - } else if ( conv2 === true ) { - conv = conv1; + // If there is no direct converter, search transitively + if ( ! conv ) { + conv1 = conv2 = undefined; + + for( conv1 in converters ) { + tmp = conv1.split( " " ); + if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) { + conv2 = converters[ tmp[ 1 ] + " " + current ]; + if ( conv2 ) { + conv1 = converters[ conv1 ]; + if ( conv1 === true ) { + conv = conv2; + } else if ( conv2 === true ) { + conv = conv1; + } + break; + } + } } } // If we found no converter, dispatch an error @@ -565,13 +589,7 @@ jQuery.extend({ // if not success, mark it as an error } else { - error = statusText = statusText || "error"; - - // Set responseText if needed - if ( response ) { - jXHR.responseText = response; - } } // Set data for the fake xhr object @@ -580,9 +598,9 @@ jQuery.extend({ // Success/Error if ( isSuccess ) { - deferred.fire( callbackContext , [ success , statusText , jXHR ] ); + deferred.resolveWith( callbackContext , [ success , statusText , jXHR ] ); } else { - deferred.fireReject( callbackContext , [ jXHR , statusText , error ] ); + deferred.rejectWith( callbackContext , [ jXHR , statusText , error ] ); } // Status-dependent callbacks @@ -596,7 +614,7 @@ jQuery.extend({ } // Complete - completeDeferred.fire( callbackContext, [ jXHR , statusText ] ); + completeDeferred.resolveWith( callbackContext, [ jXHR , statusText ] ); if ( s.global ) { globalEventContext.trigger( "ajaxComplete" , [ jXHR , s] ); @@ -630,7 +648,8 @@ jQuery.extend({ }; // Remove hash character (#7531: and string promotion) - s.url = ( "" + s.url ).replace( rhash , "" ); + // We also use the url parameter if available + s.url = ( "" + ( url || s.url ) ).replace( rhash , "" ); // Extract dataTypes list s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( /\s+/ );