@@ 7212-7593 (lines=382) @@ | ||
7209 | ajaxTransport: addToPrefiltersOrTransports( transports ), |
|
7210 | ||
7211 | // Main method |
|
7212 | ajax: function( url, options ) { |
|
7213 | ||
7214 | // If url is an object, simulate pre-1.5 signature |
|
7215 | if ( typeof url === "object" ) { |
|
7216 | options = url; |
|
7217 | url = undefined; |
|
7218 | } |
|
7219 | ||
7220 | // Force options to be an object |
|
7221 | options = options || {}; |
|
7222 | ||
7223 | var // Create the final options object |
|
7224 | s = jQuery.ajaxSetup( {}, options ), |
|
7225 | // Callbacks context |
|
7226 | callbackContext = s.context || s, |
|
7227 | // Context for global events |
|
7228 | // It's the callbackContext if one was provided in the options |
|
7229 | // and if it's a DOM node or a jQuery collection |
|
7230 | globalEventContext = callbackContext !== s && |
|
7231 | ( callbackContext.nodeType || callbackContext instanceof jQuery ) ? |
|
7232 | jQuery( callbackContext ) : jQuery.event, |
|
7233 | // Deferreds |
|
7234 | deferred = jQuery.Deferred(), |
|
7235 | completeDeferred = jQuery.Callbacks( "once memory" ), |
|
7236 | // Status-dependent callbacks |
|
7237 | statusCode = s.statusCode || {}, |
|
7238 | // ifModified key |
|
7239 | ifModifiedKey, |
|
7240 | // Headers (they are sent all at once) |
|
7241 | requestHeaders = {}, |
|
7242 | requestHeadersNames = {}, |
|
7243 | // Response headers |
|
7244 | responseHeadersString, |
|
7245 | responseHeaders, |
|
7246 | // transport |
|
7247 | transport, |
|
7248 | // timeout handle |
|
7249 | timeoutTimer, |
|
7250 | // Cross-domain detection vars |
|
7251 | parts, |
|
7252 | // The jqXHR state |
|
7253 | state = 0, |
|
7254 | // To know if global events are to be dispatched |
|
7255 | fireGlobals, |
|
7256 | // Loop variable |
|
7257 | i, |
|
7258 | // Fake xhr |
|
7259 | jqXHR = { |
|
7260 | ||
7261 | readyState: 0, |
|
7262 | ||
7263 | // Caches the header |
|
7264 | setRequestHeader: function( name, value ) { |
|
7265 | if ( !state ) { |
|
7266 | var lname = name.toLowerCase(); |
|
7267 | name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; |
|
7268 | requestHeaders[ name ] = value; |
|
7269 | } |
|
7270 | return this; |
|
7271 | }, |
|
7272 | ||
7273 | // Raw string |
|
7274 | getAllResponseHeaders: function() { |
|
7275 | return state === 2 ? responseHeadersString : null; |
|
7276 | }, |
|
7277 | ||
7278 | // Builds headers hashtable if needed |
|
7279 | getResponseHeader: function( key ) { |
|
7280 | var match; |
|
7281 | if ( state === 2 ) { |
|
7282 | if ( !responseHeaders ) { |
|
7283 | responseHeaders = {}; |
|
7284 | while( ( match = rheaders.exec( responseHeadersString ) ) ) { |
|
7285 | responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; |
|
7286 | } |
|
7287 | } |
|
7288 | match = responseHeaders[ key.toLowerCase() ]; |
|
7289 | } |
|
7290 | return match === undefined ? null : match; |
|
7291 | }, |
|
7292 | ||
7293 | // Overrides response content-type header |
|
7294 | overrideMimeType: function( type ) { |
|
7295 | if ( !state ) { |
|
7296 | s.mimeType = type; |
|
7297 | } |
|
7298 | return this; |
|
7299 | }, |
|
7300 | ||
7301 | // Cancel the request |
|
7302 | abort: function( statusText ) { |
|
7303 | statusText = statusText || "abort"; |
|
7304 | if ( transport ) { |
|
7305 | transport.abort( statusText ); |
|
7306 | } |
|
7307 | done( 0, statusText ); |
|
7308 | return this; |
|
7309 | } |
|
7310 | }; |
|
7311 | ||
7312 | // Callback for when everything is done |
|
7313 | // It is defined here because jslint complains if it is declared |
|
7314 | // at the end of the function (which would be more logical and readable) |
|
7315 | function done( status, nativeStatusText, responses, headers ) { |
|
7316 | ||
7317 | // Called once |
|
7318 | if ( state === 2 ) { |
|
7319 | return; |
|
7320 | } |
|
7321 | ||
7322 | // State is "done" now |
|
7323 | state = 2; |
|
7324 | ||
7325 | // Clear timeout if it exists |
|
7326 | if ( timeoutTimer ) { |
|
7327 | clearTimeout( timeoutTimer ); |
|
7328 | } |
|
7329 | ||
7330 | // Dereference transport for early garbage collection |
|
7331 | // (no matter how long the jqXHR object will be used) |
|
7332 | transport = undefined; |
|
7333 | ||
7334 | // Cache response headers |
|
7335 | responseHeadersString = headers || ""; |
|
7336 | ||
7337 | // Set readyState |
|
7338 | jqXHR.readyState = status > 0 ? 4 : 0; |
|
7339 | ||
7340 | var isSuccess, |
|
7341 | success, |
|
7342 | error, |
|
7343 | statusText = nativeStatusText, |
|
7344 | response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined, |
|
7345 | lastModified, |
|
7346 | etag; |
|
7347 | ||
7348 | // If successful, handle type chaining |
|
7349 | if ( status >= 200 && status < 300 || status === 304 ) { |
|
7350 | ||
7351 | // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. |
|
7352 | if ( s.ifModified ) { |
|
7353 | ||
7354 | if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) { |
|
7355 | jQuery.lastModified[ ifModifiedKey ] = lastModified; |
|
7356 | } |
|
7357 | if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) { |
|
7358 | jQuery.etag[ ifModifiedKey ] = etag; |
|
7359 | } |
|
7360 | } |
|
7361 | ||
7362 | // If not modified |
|
7363 | if ( status === 304 ) { |
|
7364 | ||
7365 | statusText = "notmodified"; |
|
7366 | isSuccess = true; |
|
7367 | ||
7368 | // If we have data |
|
7369 | } else { |
|
7370 | ||
7371 | try { |
|
7372 | success = ajaxConvert( s, response ); |
|
7373 | statusText = "success"; |
|
7374 | isSuccess = true; |
|
7375 | } catch(e) { |
|
7376 | // We have a parsererror |
|
7377 | statusText = "parsererror"; |
|
7378 | error = e; |
|
7379 | } |
|
7380 | } |
|
7381 | } else { |
|
7382 | // We extract error from statusText |
|
7383 | // then normalize statusText and status for non-aborts |
|
7384 | error = statusText; |
|
7385 | if ( !statusText || status ) { |
|
7386 | statusText = "error"; |
|
7387 | if ( status < 0 ) { |
|
7388 | status = 0; |
|
7389 | } |
|
7390 | } |
|
7391 | } |
|
7392 | ||
7393 | // Set data for the fake xhr object |
|
7394 | jqXHR.status = status; |
|
7395 | jqXHR.statusText = "" + ( nativeStatusText || statusText ); |
|
7396 | ||
7397 | // Success/Error |
|
7398 | if ( isSuccess ) { |
|
7399 | deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); |
|
7400 | } else { |
|
7401 | deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); |
|
7402 | } |
|
7403 | ||
7404 | // Status-dependent callbacks |
|
7405 | jqXHR.statusCode( statusCode ); |
|
7406 | statusCode = undefined; |
|
7407 | ||
7408 | if ( fireGlobals ) { |
|
7409 | globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), |
|
7410 | [ jqXHR, s, isSuccess ? success : error ] ); |
|
7411 | } |
|
7412 | ||
7413 | // Complete |
|
7414 | completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); |
|
7415 | ||
7416 | if ( fireGlobals ) { |
|
7417 | globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); |
|
7418 | // Handle the global AJAX counter |
|
7419 | if ( !( --jQuery.active ) ) { |
|
7420 | jQuery.event.trigger( "ajaxStop" ); |
|
7421 | } |
|
7422 | } |
|
7423 | } |
|
7424 | ||
7425 | // Attach deferreds |
|
7426 | deferred.promise( jqXHR ); |
|
7427 | jqXHR.success = jqXHR.done; |
|
7428 | jqXHR.error = jqXHR.fail; |
|
7429 | jqXHR.complete = completeDeferred.add; |
|
7430 | ||
7431 | // Status-dependent callbacks |
|
7432 | jqXHR.statusCode = function( map ) { |
|
7433 | if ( map ) { |
|
7434 | var tmp; |
|
7435 | if ( state < 2 ) { |
|
7436 | for ( tmp in map ) { |
|
7437 | statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; |
|
7438 | } |
|
7439 | } else { |
|
7440 | tmp = map[ jqXHR.status ]; |
|
7441 | jqXHR.then( tmp, tmp ); |
|
7442 | } |
|
7443 | } |
|
7444 | return this; |
|
7445 | }; |
|
7446 | ||
7447 | // Remove hash character (#7531: and string promotion) |
|
7448 | // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) |
|
7449 | // We also use the url parameter if available |
|
7450 | s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); |
|
7451 | ||
7452 | // Extract dataTypes list |
|
7453 | s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax ); |
|
7454 | ||
7455 | // Determine if a cross-domain request is in order |
|
7456 | if ( s.crossDomain == null ) { |
|
7457 | parts = rurl.exec( s.url.toLowerCase() ); |
|
7458 | s.crossDomain = !!( parts && |
|
7459 | ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] || |
|
7460 | ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != |
|
7461 | ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) ) |
|
7462 | ); |
|
7463 | } |
|
7464 | ||
7465 | // Convert data if not already a string |
|
7466 | if ( s.data && s.processData && typeof s.data !== "string" ) { |
|
7467 | s.data = jQuery.param( s.data, s.traditional ); |
|
7468 | } |
|
7469 | ||
7470 | // Apply prefilters |
|
7471 | inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); |
|
7472 | ||
7473 | // If request was aborted inside a prefiler, stop there |
|
7474 | if ( state === 2 ) { |
|
7475 | return false; |
|
7476 | } |
|
7477 | ||
7478 | // We can fire global events as of now if asked to |
|
7479 | fireGlobals = s.global; |
|
7480 | ||
7481 | // Uppercase the type |
|
7482 | s.type = s.type.toUpperCase(); |
|
7483 | ||
7484 | // Determine if request has content |
|
7485 | s.hasContent = !rnoContent.test( s.type ); |
|
7486 | ||
7487 | // Watch for a new set of requests |
|
7488 | if ( fireGlobals && jQuery.active++ === 0 ) { |
|
7489 | jQuery.event.trigger( "ajaxStart" ); |
|
7490 | } |
|
7491 | ||
7492 | // More options handling for requests with no content |
|
7493 | if ( !s.hasContent ) { |
|
7494 | ||
7495 | // If data is available, append data to url |
|
7496 | if ( s.data ) { |
|
7497 | s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; |
|
7498 | // #9682: remove data so that it's not used in an eventual retry |
|
7499 | delete s.data; |
|
7500 | } |
|
7501 | ||
7502 | // Get ifModifiedKey before adding the anti-cache parameter |
|
7503 | ifModifiedKey = s.url; |
|
7504 | ||
7505 | // Add anti-cache in url if needed |
|
7506 | if ( s.cache === false ) { |
|
7507 | ||
7508 | var ts = jQuery.now(), |
|
7509 | // try replacing _= if it is there |
|
7510 | ret = s.url.replace( rts, "$1_=" + ts ); |
|
7511 | ||
7512 | // if nothing was replaced, add timestamp to the end |
|
7513 | s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" ); |
|
7514 | } |
|
7515 | } |
|
7516 | ||
7517 | // Set the correct header, if data is being sent |
|
7518 | if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { |
|
7519 | jqXHR.setRequestHeader( "Content-Type", s.contentType ); |
|
7520 | } |
|
7521 | ||
7522 | // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. |
|
7523 | if ( s.ifModified ) { |
|
7524 | ifModifiedKey = ifModifiedKey || s.url; |
|
7525 | if ( jQuery.lastModified[ ifModifiedKey ] ) { |
|
7526 | jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] ); |
|
7527 | } |
|
7528 | if ( jQuery.etag[ ifModifiedKey ] ) { |
|
7529 | jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] ); |
|
7530 | } |
|
7531 | } |
|
7532 | ||
7533 | // Set the Accepts header for the server, depending on the dataType |
|
7534 | jqXHR.setRequestHeader( |
|
7535 | "Accept", |
|
7536 | s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? |
|
7537 | s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : |
|
7538 | s.accepts[ "*" ] |
|
7539 | ); |
|
7540 | ||
7541 | // Check for headers option |
|
7542 | for ( i in s.headers ) { |
|
7543 | jqXHR.setRequestHeader( i, s.headers[ i ] ); |
|
7544 | } |
|
7545 | ||
7546 | // Allow custom headers/mimetypes and early abort |
|
7547 | if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { |
|
7548 | // Abort if not done already |
|
7549 | jqXHR.abort(); |
|
7550 | return false; |
|
7551 | ||
7552 | } |
|
7553 | ||
7554 | // Install callbacks on deferreds |
|
7555 | for ( i in { success: 1, error: 1, complete: 1 } ) { |
|
7556 | jqXHR[ i ]( s[ i ] ); |
|
7557 | } |
|
7558 | ||
7559 | // Get transport |
|
7560 | transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); |
|
7561 | ||
7562 | // If no transport, we auto-abort |
|
7563 | if ( !transport ) { |
|
7564 | done( -1, "No Transport" ); |
|
7565 | } else { |
|
7566 | jqXHR.readyState = 1; |
|
7567 | // Send global event |
|
7568 | if ( fireGlobals ) { |
|
7569 | globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); |
|
7570 | } |
|
7571 | // Timeout |
|
7572 | if ( s.async && s.timeout > 0 ) { |
|
7573 | timeoutTimer = setTimeout( function(){ |
|
7574 | jqXHR.abort( "timeout" ); |
|
7575 | }, s.timeout ); |
|
7576 | } |
|
7577 | ||
7578 | try { |
|
7579 | state = 1; |
|
7580 | transport.send( requestHeaders, done ); |
|
7581 | } catch (e) { |
|
7582 | // Propagate exception as error if not done |
|
7583 | if ( state < 2 ) { |
|
7584 | done( -1, e ); |
|
7585 | // Simply rethrow otherwise |
|
7586 | } else { |
|
7587 | throw e; |
|
7588 | } |
|
7589 | } |
|
7590 | } |
|
7591 | ||
7592 | return jqXHR; |
|
7593 | }, |
|
7594 | ||
7595 | // Serialize an array of form elements or a set of |
|
7596 | // key/values into a query string |
@@ 6307-6658 (lines=352) @@ | ||
6304 | ajaxTransport: addToPrefiltersOrTransports( transports ), |
|
6305 | ||
6306 | // Main method |
|
6307 | ajax: function( url, options ) { |
|
6308 | ||
6309 | // If options is not an object, |
|
6310 | // we simulate pre-1.5 signature |
|
6311 | if ( typeof options !== "object" ) { |
|
6312 | options = url; |
|
6313 | url = undefined; |
|
6314 | } |
|
6315 | ||
6316 | // Force options to be an object |
|
6317 | options = options || {}; |
|
6318 | ||
6319 | var // Create the final options object |
|
6320 | s = jQuery.extend( true, {}, jQuery.ajaxSettings, options ), |
|
6321 | // Callbacks contexts |
|
6322 | // We force the original context if it exists |
|
6323 | // or take it from jQuery.ajaxSettings otherwise |
|
6324 | // (plain objects used as context get extended) |
|
6325 | callbackContext = |
|
6326 | ( s.context = ( "context" in options ? options : jQuery.ajaxSettings ).context ) || s, |
|
6327 | globalEventContext = callbackContext === s ? jQuery.event : jQuery( callbackContext ), |
|
6328 | // Deferreds |
|
6329 | deferred = jQuery.Deferred(), |
|
6330 | completeDeferred = jQuery._Deferred(), |
|
6331 | // Status-dependent callbacks |
|
6332 | statusCode = s.statusCode || {}, |
|
6333 | // Headers (they are sent all at once) |
|
6334 | requestHeaders = {}, |
|
6335 | // Response headers |
|
6336 | responseHeadersString, |
|
6337 | responseHeaders, |
|
6338 | // transport |
|
6339 | transport, |
|
6340 | // timeout handle |
|
6341 | timeoutTimer, |
|
6342 | // Cross-domain detection vars |
|
6343 | loc = document.location, |
|
6344 | protocol = loc.protocol || "http:", |
|
6345 | parts, |
|
6346 | // The jXHR state |
|
6347 | state = 0, |
|
6348 | // Loop variable |
|
6349 | i, |
|
6350 | // Fake xhr |
|
6351 | jXHR = { |
|
6352 | ||
6353 | readyState: 0, |
|
6354 | ||
6355 | // Caches the header |
|
6356 | setRequestHeader: function( name, value ) { |
|
6357 | if ( state === 0 ) { |
|
6358 | requestHeaders[ name.toLowerCase() ] = value; |
|
6359 | } |
|
6360 | return this; |
|
6361 | }, |
|
6362 | ||
6363 | // Raw string |
|
6364 | getAllResponseHeaders: function() { |
|
6365 | return state === 2 ? responseHeadersString : null; |
|
6366 | }, |
|
6367 | ||
6368 | // Builds headers hashtable if needed |
|
6369 | getResponseHeader: function( key ) { |
|
6370 | var match; |
|
6371 | if ( state === 2 ) { |
|
6372 | if ( !responseHeaders ) { |
|
6373 | responseHeaders = {}; |
|
6374 | while( ( match = rheaders.exec( responseHeadersString ) ) ) { |
|
6375 | responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; |
|
6376 | } |
|
6377 | } |
|
6378 | match = responseHeaders[ key.toLowerCase() ]; |
|
6379 | } |
|
6380 | return match || null; |
|
6381 | }, |
|
6382 | ||
6383 | // Cancel the request |
|
6384 | abort: function( statusText ) { |
|
6385 | statusText = statusText || "abort"; |
|
6386 | if ( transport ) { |
|
6387 | transport.abort( statusText ); |
|
6388 | } |
|
6389 | done( 0, statusText ); |
|
6390 | return this; |
|
6391 | } |
|
6392 | }; |
|
6393 | ||
6394 | // Callback for when everything is done |
|
6395 | // It is defined here because jslint complains if it is declared |
|
6396 | // at the end of the function (which would be more logical and readable) |
|
6397 | function done( status, statusText, responses, headers) { |
|
6398 | ||
6399 | // Called once |
|
6400 | if ( state === 2 ) { |
|
6401 | return; |
|
6402 | } |
|
6403 | ||
6404 | // State is "done" now |
|
6405 | state = 2; |
|
6406 | ||
6407 | // Clear timeout if it exists |
|
6408 | if ( timeoutTimer ) { |
|
6409 | clearTimeout( timeoutTimer ); |
|
6410 | } |
|
6411 | ||
6412 | // Dereference transport for early garbage collection |
|
6413 | // (no matter how long the jXHR object will be used) |
|
6414 | transport = undefined; |
|
6415 | ||
6416 | // Cache response headers |
|
6417 | responseHeadersString = headers || ""; |
|
6418 | ||
6419 | // Set readyState |
|
6420 | jXHR.readyState = status ? 4 : 0; |
|
6421 | ||
6422 | var isSuccess, |
|
6423 | success, |
|
6424 | error, |
|
6425 | response = responses ? ajaxHandleResponses( s, jXHR, responses ) : undefined, |
|
6426 | lastModified, |
|
6427 | etag; |
|
6428 | ||
6429 | // If successful, handle type chaining |
|
6430 | if ( status >= 200 && status < 300 || status === 304 ) { |
|
6431 | ||
6432 | // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. |
|
6433 | if ( s.ifModified ) { |
|
6434 | ||
6435 | if ( ( lastModified = jXHR.getResponseHeader( "Last-Modified" ) ) ) { |
|
6436 | jQuery.lastModified[ s.url ] = lastModified; |
|
6437 | } |
|
6438 | if ( ( etag = jXHR.getResponseHeader( "Etag" ) ) ) { |
|
6439 | jQuery.etag[ s.url ] = etag; |
|
6440 | } |
|
6441 | } |
|
6442 | ||
6443 | // If not modified |
|
6444 | if ( status === 304 ) { |
|
6445 | ||
6446 | statusText = "notmodified"; |
|
6447 | isSuccess = true; |
|
6448 | ||
6449 | // If we have data |
|
6450 | } else { |
|
6451 | ||
6452 | try { |
|
6453 | success = ajaxConvert( s, response ); |
|
6454 | statusText = "success"; |
|
6455 | isSuccess = true; |
|
6456 | } catch(e) { |
|
6457 | // We have a parsererror |
|
6458 | statusText = "parsererror"; |
|
6459 | error = e; |
|
6460 | } |
|
6461 | } |
|
6462 | } else { |
|
6463 | // We extract error from statusText |
|
6464 | // then normalize statusText and status for non-aborts |
|
6465 | error = statusText; |
|
6466 | if( status ) { |
|
6467 | statusText = "error"; |
|
6468 | if ( status < 0 ) { |
|
6469 | status = 0; |
|
6470 | } |
|
6471 | } |
|
6472 | } |
|
6473 | ||
6474 | // Set data for the fake xhr object |
|
6475 | jXHR.status = status; |
|
6476 | jXHR.statusText = statusText; |
|
6477 | ||
6478 | // Success/Error |
|
6479 | if ( isSuccess ) { |
|
6480 | deferred.resolveWith( callbackContext, [ success, statusText, jXHR ] ); |
|
6481 | } else { |
|
6482 | deferred.rejectWith( callbackContext, [ jXHR, statusText, error ] ); |
|
6483 | } |
|
6484 | ||
6485 | // Status-dependent callbacks |
|
6486 | jXHR.statusCode( statusCode ); |
|
6487 | statusCode = undefined; |
|
6488 | ||
6489 | if ( s.global ) { |
|
6490 | globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), |
|
6491 | [ jXHR, s, isSuccess ? success : error ] ); |
|
6492 | } |
|
6493 | ||
6494 | // Complete |
|
6495 | completeDeferred.resolveWith( callbackContext, [ jXHR, statusText ] ); |
|
6496 | ||
6497 | if ( s.global ) { |
|
6498 | globalEventContext.trigger( "ajaxComplete", [ jXHR, s] ); |
|
6499 | // Handle the global AJAX counter |
|
6500 | if ( !( --jQuery.active ) ) { |
|
6501 | jQuery.event.trigger( "ajaxStop" ); |
|
6502 | } |
|
6503 | } |
|
6504 | } |
|
6505 | ||
6506 | // Attach deferreds |
|
6507 | deferred.promise( jXHR ); |
|
6508 | jXHR.success = jXHR.done; |
|
6509 | jXHR.error = jXHR.fail; |
|
6510 | jXHR.complete = completeDeferred.done; |
|
6511 | ||
6512 | // Status-dependent callbacks |
|
6513 | jXHR.statusCode = function( map ) { |
|
6514 | if ( map ) { |
|
6515 | var tmp; |
|
6516 | if ( state < 2 ) { |
|
6517 | for( tmp in map ) { |
|
6518 | statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; |
|
6519 | } |
|
6520 | } else { |
|
6521 | tmp = map[ jXHR.status ]; |
|
6522 | jXHR.then( tmp, tmp ); |
|
6523 | } |
|
6524 | } |
|
6525 | return this; |
|
6526 | }; |
|
6527 | ||
6528 | // Remove hash character (#7531: and string promotion) |
|
6529 | // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) |
|
6530 | // We also use the url parameter if available |
|
6531 | s.url = ( "" + ( url || s.url ) ).replace( rhash, "" ).replace( rprotocol, protocol + "//" ); |
|
6532 | ||
6533 | // Extract dataTypes list |
|
6534 | s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax ); |
|
6535 | ||
6536 | // Determine if a cross-domain request is in order |
|
6537 | if ( !s.crossDomain ) { |
|
6538 | parts = rurl.exec( s.url.toLowerCase() ); |
|
6539 | s.crossDomain = !!( parts && |
|
6540 | ( parts[ 1 ] != protocol || parts[ 2 ] != loc.hostname || |
|
6541 | ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != |
|
6542 | ( loc.port || ( protocol === "http:" ? 80 : 443 ) ) ) |
|
6543 | ); |
|
6544 | } |
|
6545 | ||
6546 | // Convert data if not already a string |
|
6547 | if ( s.data && s.processData && typeof s.data !== "string" ) { |
|
6548 | s.data = jQuery.param( s.data, s.traditional ); |
|
6549 | } |
|
6550 | ||
6551 | // Apply prefilters |
|
6552 | inspectPrefiltersOrTransports( prefilters, s, options, jXHR ); |
|
6553 | ||
6554 | // Uppercase the type |
|
6555 | s.type = s.type.toUpperCase(); |
|
6556 | ||
6557 | // Determine if request has content |
|
6558 | s.hasContent = !rnoContent.test( s.type ); |
|
6559 | ||
6560 | // Watch for a new set of requests |
|
6561 | if ( s.global && jQuery.active++ === 0 ) { |
|
6562 | jQuery.event.trigger( "ajaxStart" ); |
|
6563 | } |
|
6564 | ||
6565 | // More options handling for requests with no content |
|
6566 | if ( !s.hasContent ) { |
|
6567 | ||
6568 | // If data is available, append data to url |
|
6569 | if ( s.data ) { |
|
6570 | s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; |
|
6571 | } |
|
6572 | ||
6573 | // Add anti-cache in url if needed |
|
6574 | if ( s.cache === false ) { |
|
6575 | ||
6576 | var ts = jQuery.now(), |
|
6577 | // try replacing _= if it is there |
|
6578 | ret = s.url.replace( rts, "$1_=" + ts ); |
|
6579 | ||
6580 | // if nothing was replaced, add timestamp to the end |
|
6581 | s.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" ); |
|
6582 | } |
|
6583 | } |
|
6584 | ||
6585 | // Set the correct header, if data is being sent |
|
6586 | if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { |
|
6587 | requestHeaders[ "content-type" ] = s.contentType; |
|
6588 | } |
|
6589 | ||
6590 | // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. |
|
6591 | if ( s.ifModified ) { |
|
6592 | if ( jQuery.lastModified[ s.url ] ) { |
|
6593 | requestHeaders[ "if-modified-since" ] = jQuery.lastModified[ s.url ]; |
|
6594 | } |
|
6595 | if ( jQuery.etag[ s.url ] ) { |
|
6596 | requestHeaders[ "if-none-match" ] = jQuery.etag[ s.url ]; |
|
6597 | } |
|
6598 | } |
|
6599 | ||
6600 | // Set the Accepts header for the server, depending on the dataType |
|
6601 | requestHeaders.accept = s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? |
|
6602 | s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) : |
|
6603 | s.accepts[ "*" ]; |
|
6604 | ||
6605 | // Check for headers option |
|
6606 | for ( i in s.headers ) { |
|
6607 | requestHeaders[ i.toLowerCase() ] = s.headers[ i ]; |
|
6608 | } |
|
6609 | ||
6610 | // Allow custom headers/mimetypes and early abort |
|
6611 | if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jXHR, s ) === false || state === 2 ) ) { |
|
6612 | // Abort if not done already |
|
6613 | done( 0, "abort" ); |
|
6614 | // Return false |
|
6615 | jXHR = false; |
|
6616 | ||
6617 | } else { |
|
6618 | ||
6619 | // Install callbacks on deferreds |
|
6620 | for ( i in { success: 1, error: 1, complete: 1 } ) { |
|
6621 | jXHR[ i ]( s[ i ] ); |
|
6622 | } |
|
6623 | ||
6624 | // Get transport |
|
6625 | transport = inspectPrefiltersOrTransports( transports, s, options, jXHR ); |
|
6626 | ||
6627 | // If no transport, we auto-abort |
|
6628 | if ( !transport ) { |
|
6629 | done( -1, "No Transport" ); |
|
6630 | } else { |
|
6631 | // Set state as sending |
|
6632 | state = jXHR.readyState = 1; |
|
6633 | // Send global event |
|
6634 | if ( s.global ) { |
|
6635 | globalEventContext.trigger( "ajaxSend", [ jXHR, s ] ); |
|
6636 | } |
|
6637 | // Timeout |
|
6638 | if ( s.async && s.timeout > 0 ) { |
|
6639 | timeoutTimer = setTimeout( function(){ |
|
6640 | jXHR.abort( "timeout" ); |
|
6641 | }, s.timeout ); |
|
6642 | } |
|
6643 | ||
6644 | try { |
|
6645 | transport.send( requestHeaders, done ); |
|
6646 | } catch (e) { |
|
6647 | // Propagate exception as error if not done |
|
6648 | if ( status < 2 ) { |
|
6649 | done( -1, e ); |
|
6650 | // Simply rethrow otherwise |
|
6651 | } else { |
|
6652 | jQuery.error( e ); |
|
6653 | } |
|
6654 | } |
|
6655 | } |
|
6656 | } |
|
6657 | return jXHR; |
|
6658 | }, |
|
6659 | ||
6660 | // Serialize an array of form elements or a set of |
|
6661 | // key/values into a query string |