X-Git-Url: http://git.asbjorn.biz/?p=jquery.git;a=blobdiff_plain;f=src%2Fajax.js;h=4830e3df8925345e9df36decb360353e4b5af629;hp=4c3f1dd53429fb3ef1eeab09a34f7fce00348374;hb=8f8961de90453274ac194479272a8dfa99ffab17;hpb=cb49b4a1b648dea8ce5b1e5dbb2ab5432a84cb63 diff --git a/src/ajax.js b/src/ajax.js index 4c3f1dd..4830e3d 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -6,6 +6,8 @@ var r20 = /%20/g, rhash = /#.*$/, rheaders = /^(.*?):\s*(.*?)\r?$/mg, // IE leaves an \r character at EOL rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /(?:^file|^widget|\-extension):$/, rnoContent = /^(?:GET|HEAD)$/, rprotocol = /^\/\//, rquery = /\?/, @@ -13,7 +15,7 @@ var r20 = /%20/g, rselectTextarea = /^(?:select|textarea)/i, rspacesAjax = /\s+/, rts = /([?&])_=[^&]*/, - rurl = /^(\w+:)\/\/([^\/?#:]+)(?::(\d+))?/, + rurl = /^([\w\+\.\-]+:)\/\/([^\/?#:]*)(?::(\d+))?/, // Keep a copy of the old load method _load = jQuery.fn.load, @@ -34,7 +36,28 @@ var r20 = /%20/g, * 2) the catchall symbol "*" can be used * 3) selection will start with transport dataType and THEN go to "*" if needed */ - transports = {}; + transports = {}, + + // Document location + ajaxLocation, + + // Document location segments + ajaxLocParts; + +// #8138, IE may throw an exception when accessing +// a field from document.location if document.domain has been set +try { + ajaxLocation = document.location.href; +} catch( e ) { + // Use the href attribute of an A element + // since IE will modify it given document.location + ajaxLocation = document.createElement( "a" ); + ajaxLocation.href = ""; + ajaxLocation = ajaxLocation.href; +} + +// Segment location into parts +ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ); // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport function addToPrefiltersOrTransports( structure ) { @@ -90,9 +113,9 @@ function inspectPrefiltersOrTransports( structure, options, originalOptions, jqX for(; i < length && ( executeOnly || !selection ); i++ ) { selection = list[ i ]( options, originalOptions, jqXHR ); // If we got redirected to another dataType - // we try there if not done already + // we try there if executing only and not done already if ( typeof selection === "string" ) { - if ( inspected[ selection ] ) { + if ( !executeOnly || inspected[ selection ] ) { selection = undefined; } else { options.dataTypes.unshift( selection ); @@ -260,7 +283,8 @@ jQuery.extend({ }, ajaxSettings: { - url: location.href, + url: ajaxLocation, + isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), global: true, type: "GET", contentType: "application/x-www-form-urlencoded", @@ -361,11 +385,11 @@ jQuery.extend({ // timeout handle timeoutTimer, // Cross-domain detection vars - loc = document.location, - protocol = loc.protocol || "http:", parts, // The jqXHR state state = 0, + // To know if global events are to be dispatched + fireGlobals, // Loop variable i, // Fake xhr @@ -507,7 +531,7 @@ jQuery.extend({ jqXHR.statusCode( statusCode ); statusCode = undefined; - if ( s.global ) { + if ( fireGlobals ) { globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), [ jqXHR, s, isSuccess ? success : error ] ); } @@ -515,7 +539,7 @@ jQuery.extend({ // Complete completeDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] ); - if ( s.global ) { + if ( fireGlobals ) { globalEventContext.trigger( "ajaxComplete", [ jqXHR, s] ); // Handle the global AJAX counter if ( !( --jQuery.active ) ) { @@ -549,7 +573,7 @@ jQuery.extend({ // Remove hash character (#7531: and string promotion) // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) // We also use the url parameter if available - s.url = ( "" + ( url || s.url ) ).replace( rhash, "" ).replace( rprotocol, protocol + "//" ); + s.url = ( "" + ( url || s.url ) ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); // Extract dataTypes list s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax ); @@ -558,9 +582,9 @@ jQuery.extend({ if ( !s.crossDomain ) { parts = rurl.exec( s.url.toLowerCase() ); s.crossDomain = !!( parts && - ( parts[ 1 ] != protocol || parts[ 2 ] != loc.hostname || + ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] || ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != - ( loc.port || ( protocol === "http:" ? 80 : 443 ) ) ) + ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) ) ); } @@ -572,6 +596,14 @@ jQuery.extend({ // Apply prefilters inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + // If request was aborted inside a prefiler, stop there + if ( state === 2 ) { + return false; + } + + // We can fire global events as of now if asked to + fireGlobals = s.global; + // Uppercase the type s.type = s.type.toUpperCase(); @@ -579,7 +611,7 @@ jQuery.extend({ s.hasContent = !rnoContent.test( s.type ); // Watch for a new set of requests - if ( s.global && jQuery.active++ === 0 ) { + if ( fireGlobals && jQuery.active++ === 0 ) { jQuery.event.trigger( "ajaxStart" ); } @@ -635,50 +667,49 @@ jQuery.extend({ // Allow custom headers/mimetypes and early abort if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { // Abort if not done already - done( 0, "abort" ); - // Return false - jqXHR = false; + jqXHR.abort(); + return false; - } else { + } - // Install callbacks on deferreds - for ( i in { success: 1, error: 1, complete: 1 } ) { - jqXHR[ i ]( s[ i ] ); - } + // Install callbacks on deferreds + for ( i in { success: 1, error: 1, complete: 1 } ) { + jqXHR[ i ]( s[ i ] ); + } - // Get transport - transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); - // If no transport, we auto-abort - if ( !transport ) { - done( -1, "No Transport" ); - } else { - // Set state as sending - state = jqXHR.readyState = 1; - // Send global event - if ( s.global ) { - globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); - } - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = setTimeout( function(){ - jqXHR.abort( "timeout" ); - }, s.timeout ); - } + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + // Set state as sending + state = jqXHR.readyState = 1; + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = setTimeout( function(){ + jqXHR.abort( "timeout" ); + }, s.timeout ); + } - try { - transport.send( requestHeaders, done ); - } catch (e) { - // Propagate exception as error if not done - if ( status < 2 ) { - done( -1, e ); - // Simply rethrow otherwise - } else { - jQuery.error( e ); - } + try { + transport.send( requestHeaders, done ); + } catch (e) { + // Propagate exception as error if not done + if ( status < 2 ) { + done( -1, e ); + // Simply rethrow otherwise + } else { + jQuery.error( e ); } } } + return jqXHR; }, @@ -698,7 +729,7 @@ jQuery.extend({ } // If an array was passed in, assume that it is an array of form elements. - if ( jQuery.isArray( a ) || a.jquery ) { + if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { // Serialize the form elements jQuery.each( a, function() { add( this.name, this.value );