+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, dataType, tested ) {
+
+ dataType = dataType || options.dataTypes[ 0 ];
+ tested = tested || {};
+
+ if ( !tested[ dataType ] ) {
+
+ tested[ dataType ] = true;
+
+ var list = structure[ dataType ],
+ i = 0,
+ length = list ? list.length : 0,
+ executeOnly = structure === prefilters,
+ selected;
+
+ for(; ( executeOnly || !selected ) && i < length; i++ ) {
+ selected = list[ i ]( options, originalOptions );
+ // If we got redirected to a different dataType,
+ // we add it and switch to the corresponding list
+ if ( typeof selected === "string" && selected !== dataType ) {
+ options.dataTypes.unshift( selected );
+ selected = inspectPrefiltersOrTransports(
+ structure, options, originalOptions, selected, tested );
+ // We always break in order not to continue
+ // to iterate in previous list
+ break;
+ }
+ }
+ // If we're only executing or nothing was selected
+ // we try the catchall dataType
+ if ( !tested[ "*" ] && ( executeOnly || ! selected ) ) {
+ selected = inspectPrefiltersOrTransports(
+ structure, options, originalOptions, "*" ,tested );
+ }
+ // This will be ignored by ajaxPrefilter
+ // so it's safe to return no matter what
+ return selected;
+ }
+}
+
+function addToPrefiltersOrTransports( structure, dataTypeExpression, functor ) {
+
+ var dataTypes = dataTypeExpression.split( rspacesAjax ),
+ i = 0,
+ length = dataTypes.length,
+ dataType,
+ list,
+ placeBefore;
+
+ // For each dataType in the dataTypeExpression
+ for(; i < length; i++ ) {
+ dataType = dataTypes[ i ];
+ // We control if we're asked to add before
+ // any existing element
+ placeBefore = /^\+/.test( dataType );
+ if ( placeBefore ) {
+ dataType = dataType.substr( 1 );
+ }
+ list = structure[ dataType ] = structure[ dataType ] || [];
+ // then we add to the structure accordingly
+ list[ placeBefore ? "unshift" : "push" ]( functor );
+ }
+}
+
+// Base function for both ajaxPrefilter and ajaxTransport
+function prefiltersOrTransports( structure, arg1, arg2, type /* internal */ ) {
+
+ type = jQuery.type( arg1 );
+
+ if ( type === "object" ) {
+ // We have an options map so we have to inspect the structure
+ return inspectPrefiltersOrTransports( structure, arg1, arg2 );
+ } else {
+ // We're requested to add to the structure
+ // Signature is ( dataTypeExpression, function )
+ // with dataTypeExpression being optional and
+ // defaulting to auto ("*")
+ type = ( type === "function" );
+ if ( type ) {
+ arg2 = arg1;
+ arg1 = undefined;
+ }
+ // We control that the second argument is really a function
+ if ( type || jQuery.isFunction( arg2 ) ) {
+ addToPrefiltersOrTransports( structure, arg1 || "*", arg2 );
+ }
+ }
+}
+
+/* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jXHR, responses ) {
+
+ var contents = s.contents,
+ dataTypes = s.dataTypes,
+ responseFields = s.responseFields,
+ ct,
+ type,
+ finalDataType,
+ firstDataType;
+
+ // Fill responseXXX fields
+ for( type in responseFields ) {
+ if ( type in responses ) {
+ jXHR[ responseFields[type] ] = responses[ type ];
+ }
+ }
+
+ // Remove auto dataType and get content-type in the process
+ while( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = jXHR.getResponseHeader( "content-type" );
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+// Chain conversions given the request and the original response
+function ajaxConvert( s, response ) {
+
+ // Apply the dataFilter if provided
+ if ( s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ var dataTypes = s.dataTypes,
+ converters = s.converters,
+ i,
+ length = dataTypes.length,
+ tmp,
+ // Current and previous dataTypes
+ current = dataTypes[ 0 ],
+ prev,
+ // Conversion expression
+ conversion,
+ // Conversion function
+ conv,
+ // Conversion functions (when text is used in-between)
+ conv1,
+ conv2;
+
+ // For each dataType in the chain
+ for( i = 1; i < length; i++ ) {
+
+ // Get the dataTypes
+ prev = current;
+ current = dataTypes[ i ];
+
+ // If current is auto dataType, update it to prev
+ if( current === "*" ) {
+ current = prev;
+ // If no auto and dataTypes are actually different
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Get the converter
+ conversion = prev + " " + current;
+ conv = converters[ conversion ] || converters[ "* " + current ];
+
+ // If there is no direct converter, search transitively
+ if ( ! conv ) {
+ 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 ( ! ( conv || conv2 ) ) {
+ jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
+ }
+ // If found converter is not an equivalence
+ if ( conv !== true ) {
+ // Convert with 1 or 2 converters accordingly
+ response = conv ? conv( response ) : conv2( conv1(response) );
+ }
+ }
+ }
+ return response;
+}
+
+})( jQuery );