Commit 64e1cdbb authored by jaubourg's avatar jaubourg

Cleans up and simplifies code shared by ajaxPrefilter and ajaxTransport....

Cleans up and simplifies code shared by ajaxPrefilter and ajaxTransport. Removes chainability of ajaxSetup, ajaxPrefilter and ajaxTransport. Also makes sure context is handled properly by ajaxSetup (unit test added).
parent 96b00a49
...@@ -161,7 +161,9 @@ jQuery.extend({ ...@@ -161,7 +161,9 @@ jQuery.extend({
ajaxSetup: function( settings ) { ajaxSetup: function( settings ) {
jQuery.extend( true, jQuery.ajaxSettings, settings ); jQuery.extend( true, jQuery.ajaxSettings, settings );
return this; if ( settings.context ) {
jQuery.ajaxSettings.context = settings.context;
}
}, },
ajaxSettings: { ajaxSettings: {
...@@ -278,6 +280,14 @@ jQuery.extend({ ...@@ -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 // Main method
ajax: function( url , options ) { ajax: function( url , options ) {
...@@ -299,7 +309,11 @@ jQuery.extend({ ...@@ -299,7 +309,11 @@ jQuery.extend({
jQuery_lastModified = jQuery.lastModified, jQuery_lastModified = jQuery.lastModified,
jQuery_etag = jQuery.etag, jQuery_etag = jQuery.etag,
// Callbacks contexts // 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 ), globalEventContext = callbackContext === s ? jQuery.event : jQuery( callbackContext ),
// Deferreds // Deferreds
deferred = jQuery.Deferred(), deferred = jQuery.Deferred(),
...@@ -373,10 +387,6 @@ jQuery.extend({ ...@@ -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 // Callback for when everything is done
// It is defined here because jslint complains if it is declared // It is defined here because jslint complains if it is declared
// at the end of the function (which would be more logical and readable) // at the end of the function (which would be more logical and readable)
...@@ -850,126 +860,97 @@ jQuery.extend({ ...@@ -850,126 +860,97 @@ jQuery.extend({
}); });
//Execute or select from functions in a given structure of options // Base function for both ajaxPrefilter and ajaxTransport
function ajax_selectOrExecute( structure , s , options ) { function ajaxPrefilterOrTransport( arg0 , arg1 , arg2 ) {
var dataTypes = s.dataTypes, var type = jQuery.type( arg1 ),
transportDataType, structure = jQuery.ajaxSettings[ arg0 ],
list,
selected,
i, i,
length, length;
checked = {},
flag, // We have an options map so we have to inspect the structure
noSelect = structure !== "transports"; if ( type === "object" ) {
function initSearch( dataType ) { var options = arg1,
originalOptions = arg2,
flag = transportDataType !== dataType && ! checked[ dataType ]; // When dealing with prefilters, we execute only
// (no selection so we never stop when a function
if ( flag ) { // returns a non-falsy, non-string value)
executeOnly = ( arg0 === "prefilters" ),
checked[ dataType ] = 1; inspect = function( dataType, tested ) {
transportDataType = dataType;
list = s[ structure ][ dataType ]; if ( ! tested[ dataType ] ) {
i = -1;
length = list ? list.length : 0 ; tested[ dataType ] = true;
}
var list = structure[ dataType ],
return flag; 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;
} }
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;
} }
// 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;
} }
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 ] );
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+/); // We're requested to add to the structure
dLength = dataTypes.length; // Signature is ( dataTypeExpression , function )
start = 1; // 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 ]; dataType = dataTypes[ i ];
// We control if we're asked to add before
first = /^\+/.test( dataType ); // any existing element
placeBefore = /^\+/.test( dataType );
if (first) { if ( placeBefore ) {
dataType = dataType.substr(1); dataType = dataType.substr( 1 );
} }
if ( dataType !== "" ) {
append = Array.prototype[ first ? "unshift" : "push" ];
list = structure[ dataType ] = structure[ dataType ] || []; list = structure[ dataType ] = structure[ dataType ] || [];
append.apply( list , functors ); // 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 ); })( jQuery );
...@@ -9,10 +9,11 @@ jQuery.ajaxSetup({ ...@@ -9,10 +9,11 @@ jQuery.ajaxSetup({
jsonpCallback: function() { jsonpCallback: function() {
return "jsonp" + jsc++; return "jsonp" + jsc++;
} }
});
// Detect, normalize options and install callbacks for jsonp requests // Detect, normalize options and install callbacks for jsonp requests
// (dataIsString is used internally) // (dataIsString is used internally)
}).ajaxPrefilter("json jsonp", function(s, originalSettings, dataIsString) { jQuery.ajaxPrefilter("json jsonp", function(s, originalSettings, dataIsString) {
dataIsString = ( typeof(s.data) === "string" ); dataIsString = ( typeof(s.data) === "string" );
......
...@@ -14,9 +14,10 @@ jQuery.ajaxSetup({ ...@@ -14,9 +14,10 @@ jQuery.ajaxSetup({
converters: { converters: {
"text script": jQuery.globalEval "text script": jQuery.globalEval
} }
});
// Handle cache's special case and global // Handle cache's special case and global
}).ajaxPrefilter("script", function(s) { jQuery.ajaxPrefilter("script", function(s) {
if ( s.cache === undefined ) { if ( s.cache === undefined ) {
s.cache = false; s.cache = false;
...@@ -26,9 +27,10 @@ jQuery.ajaxSetup({ ...@@ -26,9 +27,10 @@ jQuery.ajaxSetup({
s.type = "GET"; s.type = "GET";
s.global = false; s.global = false;
} }
});
// Bind script tag hack transport // Bind script tag hack transport
}).ajaxTransport("script", function(s) { jQuery.ajaxTransport("script", function(s) {
// This transport only deals with cross domain requests // This transport only deals with cross domain requests
if ( s.crossDomain ) { if ( s.crossDomain ) {
......
...@@ -599,6 +599,47 @@ test("jQuery.ajax context modification", function() { ...@@ -599,6 +599,47 @@ test("jQuery.ajax context modification", function() {
equals( obj.test, "foo", "Make sure the original object is maintained." ); 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() { test("jQuery.ajax() - disabled globals", function() {
expect( 3 ); expect( 3 );
stop(); stop();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment