From: John Resig Date: Thu, 20 Jan 2011 19:39:28 +0000 (-0500) Subject: Merge branch 'make_fix' of https://github.com/danheberden/jquery into danheberden... X-Git-Url: http://git.asbjorn.it/?p=jquery.git;a=commitdiff_plain;h=35875acd03cc95eace495f887511f2b61f223f7a;hp=74dfc7f2a992b8aebbd98ec75e5e0175e2616142 Merge branch 'make_fix' of https://github.com/danheberden/jquery into danheberden-make_fix --- diff --git a/src/ajax.js b/src/ajax.js index 871481d..bf0259c 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -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: { @@ -182,9 +184,6 @@ jQuery.extend({ headers: {}, crossDomain: null, */ - xhr: function() { - return new window.XMLHttpRequest(); - }, accepts: { xml: "application/xml, text/xml", @@ -200,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: @@ -235,35 +239,39 @@ jQuery.extend({ } }, + ajaxPrefilter: function( a , b ) { + ajaxPrefilterOrTransport( "prefilters" , a , b ); + }, + + ajaxTransport: function( a , b ) { + return ajaxPrefilterOrTransport( "transports" , a , b ); + }, + // Main method - // (s is used internally) - ajax: function( url , options , s ) { + 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; - - // Create the final options object - s = jQuery.extend( true , {} , jQuery.ajaxSettings , options ); - - // We force the original context - // (plain objects used as context get extended) - s.context = options.context; - - var // jQuery lists + var // Create the final options object + s = jQuery.extend( true , {} , jQuery.ajaxSettings , options ), + // jQuery lists jQuery_lastModified = jQuery.lastModified, jQuery_etag = jQuery.etag, // Callbacks contexts - callbackContext = s.context || s, - globalEventContext = s.context ? jQuery( s.context ) : jQuery.event, + // 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(), completeDeferred = jQuery._Deferred(), @@ -280,6 +288,7 @@ jQuery.extend({ timeoutTimer, // Cross-domain detection vars loc = document.location, + protocol = loc.protocol || "http:", parts, // The jXHR state state = 0, @@ -304,30 +313,25 @@ jQuery.extend({ }, // Builds headers hashtable if needed - // (match is used internally) - getResponseHeader: function( key , match ) { + getResponseHeader: function( key ) { + + var match; if ( state === 2 ) { - if ( responseHeaders === undefined ) { + if ( !responseHeaders ) { responseHeaders = {}; - if ( typeof responseHeadersString === "string" ) { - - while( ( match = rheaders.exec( responseHeadersString ) ) ) { - responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; - } + while( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; } } match = responseHeaders[ key.toLowerCase() ]; - } else { - - match = null; } - return match; + return match || null; }, // Cancel the request @@ -343,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 ) { @@ -354,8 +358,8 @@ jQuery.extend({ state = 2; // Dereference transport for early garbage collection - // (no matter how long the jXHR transport will be used - transport = 0; + // (no matter how long the jXHR object will be used) + transport = undefined; // Set readyState jXHR.readyState = status ? 4 : 0; @@ -368,17 +372,73 @@ jQuery.extend({ clearTimeout(timeoutTimer); } - var // Reference url - url = s.url, - // and ifModified status - ifModified = s.ifModified, + var // Reference dataTypes and responseFields + dataTypes = s.dataTypes, + responseFields = s.responseFields, + responseField, - // Is it a success? - isSuccess = 0, + // Flag to mark as success + isSuccess, // Stored success success, // Stored error - error; + error, + + // To keep track of statusCode based callbacks + 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; + + // Auto (xml, json, script or text determined given headers) + if ( transportDataType === "*" && ( ct = jXHR.getResponseHeader( "content-type" ) ) ) { + + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + transportDataType = dataTypes[0] = type; + break; + } + } + + type = undefined; + } + + // Get final dataType + for( type in responses ) { + if ( ! finalDataType && type === transportDataType ) { + finalDataType = type; + } + responseField = responseFields[ type ]; + if ( responseField && ! ( responseField in jXHR ) ) { + jXHR[ responseField ] = responses[ type ]; + } + } + + // If no response with the expected dataType was provided + // Take the last response as a default if it exists + if ( ! finalDataType && type ) { + finalDataType = type; + if ( transportDataType === "*" ) { + dataTypes.shift(); + } + dataTypes.unshift( finalDataType ); + } + + // Get final response + response = responses[ finalDataType ]; + } // If successful, handle type chaining if ( status >= 200 && status < 300 || status === 304 ) { @@ -400,15 +460,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 @@ -420,19 +477,15 @@ jQuery.extend({ current, // Previous dataType prev, + // Conversion expression + conversion, // Conversion function 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" - }; + // Local references to converters + converters = s.converters; // For each dataType in the chain for( i = 0 ; i < dataTypes.length ; i++ ) { @@ -441,11 +494,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 @@ -458,8 +509,8 @@ jQuery.extend({ if ( prev !== "*" && current !== "*" && prev !== current ) { // Get the converter - conv = converters[ prev + " " + current ] || - converters[ "* " + current ]; + conversion = prev + " " + current; + conv = converters[ conversion ] || converters[ "* " + current ]; conv1 = conv2 = 0; @@ -513,13 +564,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 @@ -528,13 +573,15 @@ 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 - jXHR.statusCode( statusCode ); + oldStatusCode = statusCode; + statusCode = undefined; + jXHR.statusCode( oldStatusCode ); if ( s.global ) { globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ) , @@ -542,7 +589,7 @@ jQuery.extend({ } // Complete - completeDeferred.fire( callbackContext, [ jXHR , statusText ] ); + completeDeferred.resolveWith( callbackContext, [ jXHR , statusText ] ); if ( s.global ) { globalEventContext.trigger( "ajaxComplete" , [ jXHR , s] ); @@ -562,27 +609,22 @@ jQuery.extend({ // Status-dependent callbacks jXHR.statusCode = function( map ) { if ( map ) { - var resolved = jXHR.isResolved(), - tmp; - if ( resolved || jXHR.isRejected() ) { - tmp = map[ jXHR.status ]; - if ( tmp ) { - if ( map === statusCode ) { - delete statusCode[ jXHR.status ]; - } - jXHR[ resolved ? "done" : "fail" ]( tmp ); - } - } else { + var tmp; + if ( statusCode ) { for( tmp in map ) { statusCode[ tmp ] = [ statusCode[ tmp ] , map[ tmp ] ]; } + } else { + tmp = map[ jXHR.status ]; + jXHR.done( tmp ).fail( tmp ); } } return this; }; // 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+/ ); @@ -592,9 +634,10 @@ jQuery.extend({ parts = rurl.exec( s.url.toLowerCase() ); s.crossDomain = !!( parts && - ( parts[ 1 ] && parts[ 1 ] != loc.protocol || + ( parts[ 1 ] && parts[ 1 ] != protocol || parts[ 2 ] != loc.hostname || - ( parts[ 3 ] || 80 ) != ( loc.port || 80 ) ) + ( parts[ 3 ] || ( ( parts[ 1 ] || protocol ) === "http:" ? 80 : 443 ) ) != + ( loc.port || ( protocol === "http:" ? 80 : 443 ) ) ) ); } @@ -679,7 +722,7 @@ jQuery.extend({ } // Get transport - transport = jQuery.ajaxTransport( s ); + transport = jQuery.ajaxTransport( s , options ); // If no transport, we auto-abort if ( ! transport ) { @@ -811,199 +854,97 @@ jQuery.extend({ }); -//Execute or select from functions in a given structure of options -function ajax_selectOrExecute( structure , s ) { +// 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 , determineDataType ); - - // 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 ] ); - } + }; - 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 ) { - - functors = sliceFunc.call( args , start ); + // We control that the second argument is really a function + if ( type || jQuery.isFunction( arg2 ) ) { - 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 ); - }; -} ); - -// Utility function that handles dataType when response is received -// (for those transports that can give text or xml responses) -function determineDataType( s , ct , text , xml ) { - - var 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; -} - -/* - * Create the request object; Microsoft failed to properly - * implement the XMLHttpRequest in IE7 (can't request local files), - * so we use the ActiveXObject when it is available - * Additionally XMLHttpRequest can be disabled in IE7/IE8 so - * we need a fallback. - */ -if ( window.ActiveXObject ) { - jQuery.ajaxSettings.xhr = function() { - if ( window.location.protocol !== "file:" ) { - try { - return new window.XMLHttpRequest(); - } catch( xhrError ) {} - } - - try { - return new window.ActiveXObject("Microsoft.XMLHTTP"); - } catch( activeError ) {} - }; -} - -var testXHR = jQuery.ajaxSettings.xhr(); - -// Does this browser support XHR requests? -jQuery.support.ajax = !!testXHR; - -// Does this browser support crossDomain XHR requests -jQuery.support.cors = testXHR && "withCredentials" in testXHR; - })( jQuery ); diff --git a/src/ajax/jsonp.js b/src/ajax/jsonp.js index 883876f..ff8d1f1 100644 --- a/src/ajax/jsonp.js +++ b/src/ajax/jsonp.js @@ -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" ); diff --git a/src/ajax/script.js b/src/ajax/script.js index b0e576f..bdf69dd 100644 --- a/src/ajax/script.js +++ b/src/ajax/script.js @@ -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 ) { diff --git a/src/ajax/xhr.js b/src/ajax/xhr.js index 34aa832..7a4da2d 100644 --- a/src/ajax/xhr.js +++ b/src/ajax/xhr.js @@ -7,177 +7,219 @@ var // Next active xhr id xhrs = {}, // #5280: see below - xhrUnloadAbortInstalled; + xhrUnloadAbortInstalled, + // XHR used to determine supports properties + testXHR; -jQuery.ajaxTransport( function( s , determineDataType ) { +// Create the request object +// (This is still attached to ajaxSettings for backward compatibility) +jQuery.ajaxSettings.xhr = window.ActiveXObject ? + /* Microsoft failed to properly + * implement the XMLHttpRequest in IE7 (can't request local files), + * so we use the ActiveXObject when it is available + * Additionally XMLHttpRequest can be disabled in IE7/IE8 so + * we need a fallback. + */ + function() { + if ( window.location.protocol !== "file:" ) { + try { + return new window.XMLHttpRequest(); + } catch( xhrError ) {} + } - // Cross domain only allowed if supported through XMLHttpRequest - if ( ! s.crossDomain || jQuery.support.cors ) { + try { + return new window.ActiveXObject("Microsoft.XMLHTTP"); + } catch( activeError ) {} + } : + // For all other browsers, use the standard XMLHttpRequest object + function() { + return new window.XMLHttpRequest(); + }; - var callback; +// Test if we can create an xhr object +try { + testXHR = jQuery.ajaxSettings.xhr(); +} catch( xhrCreationException ) {} - return { +//Does this browser support XHR requests? +jQuery.support.ajax = !!testXHR; - send: function(headers, complete) { +// Does this browser support crossDomain XHR requests +jQuery.support.cors = testXHR && "withCredentials" in testXHR; - // #5280: we need to abort on unload or IE will keep connections alive - if ( ! xhrUnloadAbortInstalled ) { +// No need for the temporary xhr anymore +testXHR = undefined; - xhrUnloadAbortInstalled = 1; +// Create transport if the browser can provide an xhr +if ( jQuery.support.ajax ) { + jQuery.ajaxTransport( function( s ) { - jQuery(window).bind( "unload" , function() { + // Cross domain only allowed if supported through XMLHttpRequest + if ( ! s.crossDomain || jQuery.support.cors ) { - // Abort all pending requests - jQuery.each(xhrs, function(_, xhr) { - if ( xhr.onreadystatechange ) { - xhr.onreadystatechange( 1 ); - } - }); + var callback; - }); - } + return { - // Get a new xhr - var xhr = s.xhr(), - handle; + send: function(headers, complete) { - // Open the socket - // Passing null username, generates a login popup on Opera (#2865) - if ( s.username ) { - xhr.open(s.type, s.url, s.async, s.username, s.password); - } else { - xhr.open(s.type, s.url, s.async); - } + // #5280: we need to abort on unload or IE will keep connections alive + if ( ! xhrUnloadAbortInstalled ) { - // Requested-With header - // Not set for crossDomain requests with no content - // (see why at http://trac.dojotoolkit.org/ticket/9486) - // Won't change header if already provided - if ( ! ( s.crossDomain && ! s.hasContent ) && ! headers["x-requested-with"] ) { - headers["x-requested-with"] = "XMLHttpRequest"; - } + xhrUnloadAbortInstalled = 1; + + jQuery(window).bind( "unload" , function() { + + // Abort all pending requests + jQuery.each(xhrs, function(_, xhr) { + if ( xhr.onreadystatechange ) { + xhr.onreadystatechange( 1 ); + } + }); - // Need an extra try/catch for cross domain requests in Firefox 3 - try { + }); + } - jQuery.each(headers, function(key,value) { - xhr.setRequestHeader(key,value); - }); + // Get a new xhr + var xhr = s.xhr(), + handle; - } catch(_) {} + // Open the socket + // Passing null username, generates a login popup on Opera (#2865) + if ( s.username ) { + xhr.open(s.type, s.url, s.async, s.username, s.password); + } else { + xhr.open(s.type, s.url, s.async); + } - // Do send the request - try { - xhr.send( ( s.hasContent && s.data ) || null ); - } catch(e) { - complete(0, "error", "" + e); - return; - } + // Requested-With header + // Not set for crossDomain requests with no content + // (see why at http://trac.dojotoolkit.org/ticket/9486) + // Won't change header if already provided + if ( ! ( s.crossDomain && ! s.hasContent ) && ! headers["x-requested-with"] ) { + headers["x-requested-with"] = "XMLHttpRequest"; + } - // Listener - callback = function( _ , isAbort ) { + // Need an extra try/catch for cross domain requests in Firefox 3 + try { - // Was never called and is aborted or complete - if ( callback && ( isAbort || xhr.readyState === 4 ) ) { + jQuery.each(headers, function(key,value) { + xhr.setRequestHeader(key,value); + }); - // Only called once - callback = 0; + } catch(_) {} - // Do not keep as active anymore - // and store back into pool - if (handle) { - xhr.onreadystatechange = jQuery.noop; - delete xhrs[ handle ]; - } + // Do send the request + try { + xhr.send( ( s.hasContent && s.data ) || null ); + } catch(e) { + complete(0, "error", "" + e); + return; + } + + // Listener + callback = function( _ , isAbort ) { - // If it's an abort - if ( isAbort ) { + // Was never called and is aborted or complete + if ( callback && ( isAbort || xhr.readyState === 4 ) ) { - // Abort it manually if needed - if ( xhr.readyState !== 4 ) { - xhr.abort(); + // Only called once + callback = 0; + + // Do not keep as active anymore + if (handle) { + xhr.onreadystatechange = jQuery.noop; + delete xhrs[ handle ]; } - } else { - // Get info - var status = xhr.status, - statusText, - response, - responseHeaders = xhr.getAllResponseHeaders(); + // If it's an abort + if ( isAbort ) { - try { // Firefox throws an exception when accessing statusText for faulty cross-domain requests + // Abort it manually if needed + if ( xhr.readyState !== 4 ) { + xhr.abort(); + } + } else { - statusText = xhr.statusText; + // Get info + var status = xhr.status, + statusText, + responseHeaders = xhr.getAllResponseHeaders(), + responses = {}, + xml = xhr.responseXML; - } catch( e ) { + // Construct response list + if ( xml && xml.documentElement /* #4958 */ ) { + responses.xml = xml; + } + responses.text = xhr.responseText; - statusText = ""; // We normalize with Webkit giving an empty statusText + try { // Firefox throws an exception when accessing statusText for faulty cross-domain requests - } + statusText = xhr.statusText; + + } catch( e ) { + + statusText = ""; // We normalize with Webkit giving an empty statusText + + } - // Filter status for non standard behaviours - // (so many they seem to be the actual "standard") - status = - // Opera returns 0 when it should be 304 - // Webkit returns 0 for failing cross-domain no matter the real status - status === 0 ? - ( - ! s.crossDomain || statusText ? // Webkit, Firefox: filter out faulty cross-domain requests + // Filter status for non standard behaviours + // (so many they seem to be the actual "standard") + status = + // Opera returns 0 when it should be 304 + // Webkit returns 0 for failing cross-domain no matter the real status + status === 0 ? ( - responseHeaders ? // Opera: filter out real aborts #6060 - 304 + ! s.crossDomain || statusText ? // Webkit, Firefox: filter out faulty cross-domain requests + ( + responseHeaders ? // Opera: filter out real aborts #6060 + 304 + : + 0 + ) : - 0 + 302 // We assume 302 but could be anything cross-domain related ) : - 302 // We assume 302 but could be anything cross-domain related - ) - : - ( - status == 1223 ? // IE sometimes returns 1223 when it should be 204 (see #1450) - 204 - : - status - ); - - // Guess response & update dataType accordingly - response = - determineDataType( - s, - xhr.getResponseHeader("content-type"), - xhr.responseText, - xhr.responseXML ); - - // Call complete - complete(status,statusText,response,responseHeaders); + ( + status == 1223 ? // IE sometimes returns 1223 when it should be 204 (see #1450) + 204 + : + status + ); + + // Call complete + complete(status,statusText,responses,responseHeaders); + } } - } - }; + }; - // if we're in sync mode - // or it's in cache and has been retrieved directly (IE6 & IE7) - // we need to manually fire the callback - if ( ! s.async || xhr.readyState === 4 ) { + // if we're in sync mode + // or it's in cache and has been retrieved directly (IE6 & IE7) + // we need to manually fire the callback + if ( ! s.async || xhr.readyState === 4 ) { - callback(); + callback(); - } else { + } else { - // Add to list of active xhrs - handle = xhrId++; - xhrs[ handle ] = xhr; - xhr.onreadystatechange = callback; - } - }, + // Add to list of active xhrs + handle = xhrId++; + xhrs[ handle ] = xhr; + xhr.onreadystatechange = callback; + } + }, - abort: function() { - if ( callback ) { - callback(0,1); + abort: function() { + if ( callback ) { + callback(0,1); + } } - } - }; - } -}); + }; + } + }); +} })( jQuery ); diff --git a/src/core.js b/src/core.js index f116ef4..236f84d 100644 --- a/src/core.js +++ b/src/core.js @@ -134,7 +134,7 @@ jQuery.fn = jQuery.prototype = { } return jQuery.merge( this, selector ); - + // HANDLE: $("#id") } else { elem = document.getElementById( match[2] ); @@ -158,13 +158,6 @@ jQuery.fn = jQuery.prototype = { return this; } - // HANDLE: $("TAG") - } else if ( !context && !rnonword.test( selector ) ) { - this.selector = selector; - this.context = document; - selector = document.getElementsByTagName( selector ); - return jQuery.merge( this, selector ); - // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return (context || rootjQuery).find( selector ); @@ -406,7 +399,7 @@ jQuery.extend({ } // If there are functions bound, to execute - readyList.fire( document , [ jQuery ] ); + readyList.resolveWith( document , [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.trigger ) { @@ -844,7 +837,7 @@ jQuery.extend({ } if ( _fired ) { - deferred.fire( _fired[ 0 ] , _fired[ 1 ] ); + deferred.resolveWith( _fired[ 0 ] , _fired[ 1 ] ); } } @@ -852,7 +845,7 @@ jQuery.extend({ }, // resolve with given context and args - fire: function( context , args ) { + resolveWith: function( context , args ) { if ( ! cancelled && ! fired && ! firing ) { firing = 1; @@ -872,7 +865,7 @@ jQuery.extend({ // resolve with this as context and given arguments resolve: function() { - deferred.fire( jQuery.isFunction( this.promise ) ? this.promise() : this , arguments ); + deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this , arguments ); return this; }, @@ -908,7 +901,7 @@ jQuery.extend({ return this; }, fail: failDeferred.done, - fireReject: failDeferred.fire, + rejectWith: failDeferred.resolveWith, reject: failDeferred.resolve, isRejected: failDeferred.isResolved, // Get a promise for this deferred @@ -961,10 +954,10 @@ jQuery.extend({ args = arguments; resolveArray[ index ] = args.length > 1 ? slice.call( args , 0 ) : value; if( ! --length ) { - deferred.fire( promise, resolveArray ); + deferred.resolveWith( promise, resolveArray ); } }).fail( function() { - deferred.fireReject( promise, arguments ); + deferred.rejectWith( promise, arguments ); }); return !deferred.isRejected(); }); diff --git a/test/unit/ajax.js b/test/unit/ajax.js index 3f672ae..1ed15b5 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -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(); @@ -1857,10 +1898,6 @@ test("jQuery ajax - atom+xml", function() { }); -test("jQuery.ajax - active counter", function() { - ok( jQuery.active == 0, "ajax active counter should be zero: " + jQuery.active ); -}); - test( "jQuery.ajax - Location object as url (#7531)", 1, function () { var success = false; try { @@ -1874,9 +1911,9 @@ test( "jQuery.ajax - Location object as url (#7531)", 1, function () { test( "jQuery.ajax - statusCode" , function() { - var count = 10; + var count = 12; - expect( 16 ); + expect( 20 ); stop(); function countComplete() { @@ -1938,8 +1975,39 @@ test( "jQuery.ajax - statusCode" , function() { } }).statusCode( createStatusCodes( "all (immediately with method)" , isSuccess ) ); + var testString = ""; + + jQuery.ajax( url( uri ), { + success: function( a , b , jXHR ) { + ok( isSuccess , "success" ); + var statusCode = {}; + statusCode[ jXHR.status ] = function() { + testString += "B"; + }; + jXHR.statusCode( statusCode ); + testString += "A"; + }, + error: function( jXHR ) { + ok( ! isSuccess , "error" ); + var statusCode = {}; + statusCode[ jXHR.status ] = function() { + testString += "B"; + }; + jXHR.statusCode( statusCode ); + testString += "A"; + }, + complete: function() { + strictEqual( testString , "AB" , "Test statusCode callbacks are ordered like " + + ( isSuccess ? "success" : "error" ) + " callbacks" ); + countComplete(); + } + } ); + }); +}); +test("jQuery.ajax - active counter", function() { + ok( jQuery.active == 0, "ajax active counter should be zero: " + jQuery.active ); }); } diff --git a/test/unit/core.js b/test/unit/core.js index 8e57edf..30039bf 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -1002,7 +1002,7 @@ test("jQuery._Deferred()", function() { deferred = jQuery._Deferred(); - deferred.fire( jQuery , [ document ] ).done( function( doc ) { + deferred.resolveWith( jQuery , [ document ] ).done( function( doc ) { ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" ); }); });