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:
// 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)
- determineResponse: function( responses , ct ) {
-
- 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 ( ct && transportDataType === "*" ) {
-
- for ( type in contents ) {
- if ( ( regexp = contents[ type ] ) && regexp.test( ct ) ) {
- transportDataType = dataTypes[0] = type;
- break;
- }
- }
- }
-
- // Get response
- for( type in responses ) {
- if ( type === transportDataType ) {
- break;
- }
- }
-
- // Get final response
- response = responses[ type ];
-
- // If it's not the right dataType, handle the dataTypeList
- if ( transportDataType !== type ) {
- if ( transportDataType === "*" ) {
- dataTypes.shift();
- }
- dataTypes.unshift( type );
- }
-
- return response;
}
-
},
ajaxPrefilter: function( a , b ) {
// 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 ) {
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
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 ) {
// 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
try {
var i,
+ tmp,
// Current dataType
current,
// Previous dataType
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++ ) {
// 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
// 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
// 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