| @@ 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 |
|