Cleans up and simplifies code shared by ajaxPrefilter and ajaxTransport. Removes...
authorjaubourg <j@ubourg.net>
Thu, 20 Jan 2011 03:12:15 +0000 (04:12 +0100)
committerjaubourg <j@ubourg.net>
Thu, 20 Jan 2011 03:12:15 +0000 (04:12 +0100)
src/ajax.js
src/ajax/jsonp.js
src/ajax/script.js
test/unit/ajax.js

index cbe5572..fc1ecfd 100644 (file)
@@ -161,7 +161,9 @@ jQuery.extend({
 
        ajaxSetup: function( settings ) {
                jQuery.extend( true, jQuery.ajaxSettings, settings );
-               return this;
+               if ( settings.context ) {
+                       jQuery.ajaxSettings.context = settings.context;
+               }
        },
 
        ajaxSettings: {
@@ -278,6 +280,14 @@ jQuery.extend({
 
        },
 
+       ajaxPrefilter: function( a , b ) {
+               ajaxPrefilterOrTransport( "prefilters" , a , b );
+       },
+
+       ajaxTransport: function( a , b ) {
+               return ajaxPrefilterOrTransport( "transports" , a , b );
+       },
+
        // Main method
        ajax: function( url , options ) {
 
@@ -299,7 +309,11 @@ jQuery.extend({
                        jQuery_lastModified = jQuery.lastModified,
                        jQuery_etag = jQuery.etag,
                        // Callbacks contexts
-                       callbackContext = options.context || s.context || s,
+                       // We force the original context if it exists
+                       // or take it from jQuery.ajaxSettings otherwise
+                       // (plain objects used as context get extended)
+                       callbackContext =
+                               ( s.context = ( "context" in options ? options : jQuery.ajaxSettings ).context ) || s,
                        globalEventContext = callbackContext === s ? jQuery.event : jQuery( callbackContext ),
                        // Deferreds
                        deferred = jQuery.Deferred(),
@@ -373,10 +387,6 @@ jQuery.extend({
                                }
                        };
 
-               // We force the original context
-               // (plain objects used as context get extended)
-               s.context = options.context;
-
                // 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)
@@ -850,126 +860,97 @@ jQuery.extend({
 
 });
 
-//Execute or select from functions in a given structure of options
-function ajax_selectOrExecute( structure , s , options ) {
+// Base function for both ajaxPrefilter and ajaxTransport
+function ajaxPrefilterOrTransport( arg0 , arg1 , arg2 ) {
 
-       var dataTypes = s.dataTypes,
-               transportDataType,
-               list,
-               selected,
+       var type = jQuery.type( arg1 ),
+               structure = jQuery.ajaxSettings[ arg0 ],
                i,
-               length,
-               checked = {},
-               flag,
-               noSelect = structure !== "transports";
-
-       function initSearch( dataType ) {
-
-               flag = transportDataType !== dataType && ! checked[ dataType ];
-
-               if ( flag ) {
-
-                       checked[ dataType ] = 1;
-                       transportDataType = dataType;
-                       list = s[ structure ][ dataType ];
-                       i = -1;
-                       length = list ? list.length : 0 ;
-               }
-
-               return flag;
-       }
-
-       initSearch( dataTypes[ 0 ] );
-
-       for ( i = 0 ; ( noSelect || ! selected ) && i <= length ; i++ ) {
-
-               if ( i === length ) {
-
-                       initSearch( "*" );
-
-               } else {
-
-                       selected = list[ i ]( s , options );
-
-                       // If we got redirected to another dataType
-                       // Search there (if not in progress or already tried)
-                       if ( typeof( selected ) === "string" &&
-                               initSearch( selected ) ) {
-
-                               dataTypes.unshift( selected );
-                               selected = 0;
-                       }
-               }
-       }
-
-       return noSelect ? jQuery : selected;
-}
-
-// Add an element to one of the structures in ajaxSettings
-function ajax_addElement( structure , args ) {
-
-       var i,
-               start = 0,
-               length = args.length,
-               dataTypes = [ "*" ],
-               dLength = 1,
-               dataType,
-               functors = [],
-               first,
-               append,
-               list;
-
-       if ( length ) {
-
-               first = jQuery.type( args[ 0 ] );
+               length;
+
+       // We have an options map so we have to inspect the structure
+       if ( type === "object" ) {
+
+               var options = arg1,
+                       originalOptions = arg2,
+                       // When dealing with prefilters, we execute only
+                       // (no selection so we never stop when a function
+                       // returns a non-falsy, non-string value)
+                       executeOnly = ( arg0 === "prefilters" ),
+                       inspect = function( dataType, tested ) {
+
+                               if ( ! tested[ dataType ] ) {
+
+                                       tested[ dataType ] = true;
+
+                                       var list = structure[ dataType ],
+                                               selected;
+
+                                       for( i = 0, length = list ? list.length : 0 ; ( 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 = inspect( 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 ( executeOnly || ! selected ) {
+                                               selected = inspect( "*" , tested );
+                                       }
+                                       // This will be ignored by ajaxPrefilter
+                                       // so it's safe to return no matter what
+                                       return selected;
+                               }
 
-               if ( first === "object" ) {
-                       return ajax_selectOrExecute( structure , args[ 0 ] , args[ 1 ] );
-               }
+                       };
 
-               structure = jQuery.ajaxSettings[ structure ];
+               // Start inspection with current transport dataType
+               return inspect( options.dataTypes[ 0 ] , {} );
 
-               if ( first !== "function" ) {
+       } else {
 
-                       dataTypes = args[ 0 ].toLowerCase().split(/\s+/);
-                       dLength = dataTypes.length;
-                       start = 1;
+               // We're requested to add to the structure
+               // Signature is ( dataTypeExpression , function )
+               // with dataTypeExpression being optional and
+               // defaulting to catchAll (*)
+               type = type === "function";
 
+               if ( type ) {
+                       arg2 = arg1;
+                       arg1 = undefined;
                }
+               arg1 = arg1 || "*";
 
-               if ( dLength && start < length ) {
+               // We control that the second argument is really a function
+               if ( type || jQuery.isFunction( arg2 ) ) {
 
-                       functors = sliceFunc.call( args , start );
-
-                       for( i = 0 ; i < dLength ; i++ ) {
+                       var dataTypes = arg1.split( /\s+/ ),
+                               functor = arg2,
+                               dataType,
+                               list,
+                               placeBefore;
 
+                       // For each dataType in the dataTypeExpression
+                       for( i = 0 , length = dataTypes.length ; i < length ; i++ ) {
                                dataType = dataTypes[ i ];
-
-                               first = /^\+/.test( dataType );
-
-                               if (first) {
-                                       dataType = dataType.substr(1);
-                               }
-
-                               if ( dataType !== "" ) {
-
-                                       append = Array.prototype[ first ? "unshift" : "push" ];
-                                       list = structure[ dataType ] = structure[ dataType ] || [];
-                                       append.apply( list , functors );
+                               // 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 );
                        }
                }
        }
-
-       return jQuery;
 }
 
-// Install prefilter & transport methods
-jQuery.each( [ "Prefilter" , "Transport" ] , function( _ , name ) {
-       _ = name.toLowerCase() + "s";
-       jQuery[ "ajax" + name ] = function() {
-               return ajax_addElement( _ , arguments );
-       };
-} );
-
 })( jQuery );
index 883876f..ff8d1f1 100644 (file)
@@ -9,10 +9,11 @@ jQuery.ajaxSetup({
        jsonpCallback: function() {
                return "jsonp" + jsc++;
        }
+});
 
 // Detect, normalize options and install callbacks for jsonp requests
 // (dataIsString is used internally)
-}).ajaxPrefilter("json jsonp", function(s, originalSettings, dataIsString) {
+jQuery.ajaxPrefilter("json jsonp", function(s, originalSettings, dataIsString) {
 
        dataIsString = ( typeof(s.data) === "string" );
 
index b0e576f..bdf69dd 100644 (file)
@@ -14,9 +14,10 @@ jQuery.ajaxSetup({
        converters: {
                "text script": jQuery.globalEval
        }
+});
 
 // Handle cache's special case and global
-}).ajaxPrefilter("script", function(s) {
+jQuery.ajaxPrefilter("script", function(s) {
 
        if ( s.cache === undefined ) {
                s.cache = false;
@@ -26,9 +27,10 @@ jQuery.ajaxSetup({
                s.type = "GET";
                s.global = false;
        }
+});
 
 // Bind script tag hack transport
-}).ajaxTransport("script", function(s) {
+jQuery.ajaxTransport("script", function(s) {
 
        // This transport only deals with cross domain requests
        if ( s.crossDomain ) {
index 52b0597..d262988 100644 (file)
@@ -599,6 +599,47 @@ test("jQuery.ajax context modification", function() {
        equals( obj.test, "foo", "Make sure the original object is maintained." );
 });
 
+test("jQuery.ajax context modification through ajaxSetup", function() {
+       expect(4);
+
+       stop();
+
+       var obj = {};
+
+       jQuery.ajaxSetup({
+               context: obj
+       });
+
+       strictEqual( jQuery.ajaxSettings.context, obj, "Make sure the context is properly set in ajaxSettings." );
+
+       jQuery.ajax({
+               url: url("data/name.html"),
+               complete: function() {
+                       strictEqual( this, obj, "Make sure the original object is maintained." );
+                       jQuery.ajax({
+                               url: url("data/name.html"),
+                               context: {},
+                               complete: function() {
+                                       ok( this !== obj, "Make sure overidding context is possible." );
+                                       jQuery.ajaxSetup({
+                                               context: false
+                                       });
+                                       jQuery.ajax({
+                                               url: url("data/name.html"),
+                                               beforeSend: function(){
+                                                       this.test = "foo2";
+                                               },
+                                               complete: function() {
+                                                       ok( this !== obj, "Make sure unsetting context is possible." );
+                                                       start();
+                                               }
+                                       });
+                               }
+                       });
+               }
+       });
+});
+
 test("jQuery.ajax() - disabled globals", function() {
        expect( 3 );
        stop();