You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ajax.js 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. define( [
  2. "./core",
  3. "./var/document",
  4. "./var/rnotwhite",
  5. "./ajax/var/location",
  6. "./ajax/var/nonce",
  7. "./ajax/var/rquery",
  8. "./core/init",
  9. "./ajax/parseJSON",
  10. "./ajax/parseXML",
  11. "./event/trigger",
  12. "./deferred"
  13. ], function( jQuery, document, rnotwhite, location, nonce, rquery ) {
  14. var
  15. rhash = /#.*$/,
  16. rts = /([?&])_=[^&]*/,
  17. rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
  18. // #7653, #8125, #8152: local protocol detection
  19. rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
  20. rnoContent = /^(?:GET|HEAD)$/,
  21. rprotocol = /^\/\//,
  22. /* Prefilters
  23. * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
  24. * 2) These are called:
  25. * - BEFORE asking for a transport
  26. * - AFTER param serialization (s.data is a string if s.processData is true)
  27. * 3) key is the dataType
  28. * 4) the catchall symbol "*" can be used
  29. * 5) execution will start with transport dataType and THEN continue down to "*" if needed
  30. */
  31. prefilters = {},
  32. /* Transports bindings
  33. * 1) key is the dataType
  34. * 2) the catchall symbol "*" can be used
  35. * 3) selection will start with transport dataType and THEN go to "*" if needed
  36. */
  37. transports = {},
  38. // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
  39. allTypes = "*/".concat( "*" ),
  40. // Anchor tag for parsing the document origin
  41. originAnchor = document.createElement( "a" );
  42. originAnchor.href = location.href;
  43. // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
  44. function addToPrefiltersOrTransports( structure ) {
  45. // dataTypeExpression is optional and defaults to "*"
  46. return function( dataTypeExpression, func ) {
  47. if ( typeof dataTypeExpression !== "string" ) {
  48. func = dataTypeExpression;
  49. dataTypeExpression = "*";
  50. }
  51. var dataType,
  52. i = 0,
  53. dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
  54. if ( jQuery.isFunction( func ) ) {
  55. // For each dataType in the dataTypeExpression
  56. while ( ( dataType = dataTypes[ i++ ] ) ) {
  57. // Prepend if requested
  58. if ( dataType[ 0 ] === "+" ) {
  59. dataType = dataType.slice( 1 ) || "*";
  60. ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
  61. // Otherwise append
  62. } else {
  63. ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
  64. }
  65. }
  66. }
  67. };
  68. }
  69. // Base inspection function for prefilters and transports
  70. function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
  71. var inspected = {},
  72. seekingTransport = ( structure === transports );
  73. function inspect( dataType ) {
  74. var selected;
  75. inspected[ dataType ] = true;
  76. jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
  77. var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
  78. if ( typeof dataTypeOrTransport === "string" &&
  79. !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
  80. options.dataTypes.unshift( dataTypeOrTransport );
  81. inspect( dataTypeOrTransport );
  82. return false;
  83. } else if ( seekingTransport ) {
  84. return !( selected = dataTypeOrTransport );
  85. }
  86. } );
  87. return selected;
  88. }
  89. return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
  90. }
  91. // A special extend for ajax options
  92. // that takes "flat" options (not to be deep extended)
  93. // Fixes #9887
  94. function ajaxExtend( target, src ) {
  95. var key, deep,
  96. flatOptions = jQuery.ajaxSettings.flatOptions || {};
  97. for ( key in src ) {
  98. if ( src[ key ] !== undefined ) {
  99. ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
  100. }
  101. }
  102. if ( deep ) {
  103. jQuery.extend( true, target, deep );
  104. }
  105. return target;
  106. }
  107. /* Handles responses to an ajax request:
  108. * - finds the right dataType (mediates between content-type and expected dataType)
  109. * - returns the corresponding response
  110. */
  111. function ajaxHandleResponses( s, jqXHR, responses ) {
  112. var ct, type, finalDataType, firstDataType,
  113. contents = s.contents,
  114. dataTypes = s.dataTypes;
  115. // Remove auto dataType and get content-type in the process
  116. while ( dataTypes[ 0 ] === "*" ) {
  117. dataTypes.shift();
  118. if ( ct === undefined ) {
  119. ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
  120. }
  121. }
  122. // Check if we're dealing with a known content-type
  123. if ( ct ) {
  124. for ( type in contents ) {
  125. if ( contents[ type ] && contents[ type ].test( ct ) ) {
  126. dataTypes.unshift( type );
  127. break;
  128. }
  129. }
  130. }
  131. // Check to see if we have a response for the expected dataType
  132. if ( dataTypes[ 0 ] in responses ) {
  133. finalDataType = dataTypes[ 0 ];
  134. } else {
  135. // Try convertible dataTypes
  136. for ( type in responses ) {
  137. if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
  138. finalDataType = type;
  139. break;
  140. }
  141. if ( !firstDataType ) {
  142. firstDataType = type;
  143. }
  144. }
  145. // Or just use first one
  146. finalDataType = finalDataType || firstDataType;
  147. }
  148. // If we found a dataType
  149. // We add the dataType to the list if needed
  150. // and return the corresponding response
  151. if ( finalDataType ) {
  152. if ( finalDataType !== dataTypes[ 0 ] ) {
  153. dataTypes.unshift( finalDataType );
  154. }
  155. return responses[ finalDataType ];
  156. }
  157. }
  158. /* Chain conversions given the request and the original response
  159. * Also sets the responseXXX fields on the jqXHR instance
  160. */
  161. function ajaxConvert( s, response, jqXHR, isSuccess ) {
  162. var conv2, current, conv, tmp, prev,
  163. converters = {},
  164. // Work with a copy of dataTypes in case we need to modify it for conversion
  165. dataTypes = s.dataTypes.slice();
  166. // Create converters map with lowercased keys
  167. if ( dataTypes[ 1 ] ) {
  168. for ( conv in s.converters ) {
  169. converters[ conv.toLowerCase() ] = s.converters[ conv ];
  170. }
  171. }
  172. current = dataTypes.shift();
  173. // Convert to each sequential dataType
  174. while ( current ) {
  175. if ( s.responseFields[ current ] ) {
  176. jqXHR[ s.responseFields[ current ] ] = response;
  177. }
  178. // Apply the dataFilter if provided
  179. if ( !prev && isSuccess && s.dataFilter ) {
  180. response = s.dataFilter( response, s.dataType );
  181. }
  182. prev = current;
  183. current = dataTypes.shift();
  184. if ( current ) {
  185. // There's only work to do if current dataType is non-auto
  186. if ( current === "*" ) {
  187. current = prev;
  188. // Convert response if prev dataType is non-auto and differs from current
  189. } else if ( prev !== "*" && prev !== current ) {
  190. // Seek a direct converter
  191. conv = converters[ prev + " " + current ] || converters[ "* " + current ];
  192. // If none found, seek a pair
  193. if ( !conv ) {
  194. for ( conv2 in converters ) {
  195. // If conv2 outputs current
  196. tmp = conv2.split( " " );
  197. if ( tmp[ 1 ] === current ) {
  198. // If prev can be converted to accepted input
  199. conv = converters[ prev + " " + tmp[ 0 ] ] ||
  200. converters[ "* " + tmp[ 0 ] ];
  201. if ( conv ) {
  202. // Condense equivalence converters
  203. if ( conv === true ) {
  204. conv = converters[ conv2 ];
  205. // Otherwise, insert the intermediate dataType
  206. } else if ( converters[ conv2 ] !== true ) {
  207. current = tmp[ 0 ];
  208. dataTypes.unshift( tmp[ 1 ] );
  209. }
  210. break;
  211. }
  212. }
  213. }
  214. }
  215. // Apply converter (if not an equivalence)
  216. if ( conv !== true ) {
  217. // Unless errors are allowed to bubble, catch and return them
  218. if ( conv && s.throws ) {
  219. response = conv( response );
  220. } else {
  221. try {
  222. response = conv( response );
  223. } catch ( e ) {
  224. return {
  225. state: "parsererror",
  226. error: conv ? e : "No conversion from " + prev + " to " + current
  227. };
  228. }
  229. }
  230. }
  231. }
  232. }
  233. }
  234. return { state: "success", data: response };
  235. }
  236. jQuery.extend( {
  237. // Counter for holding the number of active queries
  238. active: 0,
  239. // Last-Modified header cache for next request
  240. lastModified: {},
  241. etag: {},
  242. ajaxSettings: {
  243. url: location.href,
  244. type: "GET",
  245. isLocal: rlocalProtocol.test( location.protocol ),
  246. global: true,
  247. processData: true,
  248. async: true,
  249. contentType: "application/x-www-form-urlencoded; charset=UTF-8",
  250. /*
  251. timeout: 0,
  252. data: null,
  253. dataType: null,
  254. username: null,
  255. password: null,
  256. cache: null,
  257. throws: false,
  258. traditional: false,
  259. headers: {},
  260. */
  261. accepts: {
  262. "*": allTypes,
  263. text: "text/plain",
  264. html: "text/html",
  265. xml: "application/xml, text/xml",
  266. json: "application/json, text/javascript"
  267. },
  268. contents: {
  269. xml: /\bxml\b/,
  270. html: /\bhtml/,
  271. json: /\bjson\b/
  272. },
  273. responseFields: {
  274. xml: "responseXML",
  275. text: "responseText",
  276. json: "responseJSON"
  277. },
  278. // Data converters
  279. // Keys separate source (or catchall "*") and destination types with a single space
  280. converters: {
  281. // Convert anything to text
  282. "* text": String,
  283. // Text to html (true = no transformation)
  284. "text html": true,
  285. // Evaluate text as a json expression
  286. "text json": jQuery.parseJSON,
  287. // Parse text as xml
  288. "text xml": jQuery.parseXML
  289. },
  290. // For options that shouldn't be deep extended:
  291. // you can add your own custom options here if
  292. // and when you create one that shouldn't be
  293. // deep extended (see ajaxExtend)
  294. flatOptions: {
  295. url: true,
  296. context: true
  297. }
  298. },
  299. // Creates a full fledged settings object into target
  300. // with both ajaxSettings and settings fields.
  301. // If target is omitted, writes into ajaxSettings.
  302. ajaxSetup: function( target, settings ) {
  303. return settings ?
  304. // Building a settings object
  305. ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
  306. // Extending ajaxSettings
  307. ajaxExtend( jQuery.ajaxSettings, target );
  308. },
  309. ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
  310. ajaxTransport: addToPrefiltersOrTransports( transports ),
  311. // Main method
  312. ajax: function( url, options ) {
  313. // If url is an object, simulate pre-1.5 signature
  314. if ( typeof url === "object" ) {
  315. options = url;
  316. url = undefined;
  317. }
  318. // Force options to be an object
  319. options = options || {};
  320. var transport,
  321. // URL without anti-cache param
  322. cacheURL,
  323. // Response headers
  324. responseHeadersString,
  325. responseHeaders,
  326. // timeout handle
  327. timeoutTimer,
  328. // Url cleanup var
  329. urlAnchor,
  330. // To know if global events are to be dispatched
  331. fireGlobals,
  332. // Loop variable
  333. i,
  334. // Create the final options object
  335. s = jQuery.ajaxSetup( {}, options ),
  336. // Callbacks context
  337. callbackContext = s.context || s,
  338. // Context for global events is callbackContext if it is a DOM node or jQuery collection
  339. globalEventContext = s.context &&
  340. ( callbackContext.nodeType || callbackContext.jquery ) ?
  341. jQuery( callbackContext ) :
  342. jQuery.event,
  343. // Deferreds
  344. deferred = jQuery.Deferred(),
  345. completeDeferred = jQuery.Callbacks( "once memory" ),
  346. // Status-dependent callbacks
  347. statusCode = s.statusCode || {},
  348. // Headers (they are sent all at once)
  349. requestHeaders = {},
  350. requestHeadersNames = {},
  351. // The jqXHR state
  352. state = 0,
  353. // Default abort message
  354. strAbort = "canceled",
  355. // Fake xhr
  356. jqXHR = {
  357. readyState: 0,
  358. // Builds headers hashtable if needed
  359. getResponseHeader: function( key ) {
  360. var match;
  361. if ( state === 2 ) {
  362. if ( !responseHeaders ) {
  363. responseHeaders = {};
  364. while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
  365. responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
  366. }
  367. }
  368. match = responseHeaders[ key.toLowerCase() ];
  369. }
  370. return match == null ? null : match;
  371. },
  372. // Raw string
  373. getAllResponseHeaders: function() {
  374. return state === 2 ? responseHeadersString : null;
  375. },
  376. // Caches the header
  377. setRequestHeader: function( name, value ) {
  378. var lname = name.toLowerCase();
  379. if ( !state ) {
  380. name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
  381. requestHeaders[ name ] = value;
  382. }
  383. return this;
  384. },
  385. // Overrides response content-type header
  386. overrideMimeType: function( type ) {
  387. if ( !state ) {
  388. s.mimeType = type;
  389. }
  390. return this;
  391. },
  392. // Status-dependent callbacks
  393. statusCode: function( map ) {
  394. var code;
  395. if ( map ) {
  396. if ( state < 2 ) {
  397. for ( code in map ) {
  398. // Lazy-add the new callback in a way that preserves old ones
  399. statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
  400. }
  401. } else {
  402. // Execute the appropriate callbacks
  403. jqXHR.always( map[ jqXHR.status ] );
  404. }
  405. }
  406. return this;
  407. },
  408. // Cancel the request
  409. abort: function( statusText ) {
  410. var finalText = statusText || strAbort;
  411. if ( transport ) {
  412. transport.abort( finalText );
  413. }
  414. done( 0, finalText );
  415. return this;
  416. }
  417. };
  418. // Attach deferreds
  419. deferred.promise( jqXHR ).complete = completeDeferred.add;
  420. jqXHR.success = jqXHR.done;
  421. jqXHR.error = jqXHR.fail;
  422. // Remove hash character (#7531: and string promotion)
  423. // Add protocol if not provided (prefilters might expect it)
  424. // Handle falsy url in the settings object (#10093: consistency with old signature)
  425. // We also use the url parameter if available
  426. s.url = ( ( url || s.url || location.href ) + "" ).replace( rhash, "" )
  427. .replace( rprotocol, location.protocol + "//" );
  428. // Alias method option to type as per ticket #12004
  429. s.type = options.method || options.type || s.method || s.type;
  430. // Extract dataTypes list
  431. s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
  432. // A cross-domain request is in order when the origin doesn't match the current origin.
  433. if ( s.crossDomain == null ) {
  434. urlAnchor = document.createElement( "a" );
  435. // Support: IE8-11+
  436. // IE throws exception if url is malformed, e.g. http://example.com:80x/
  437. try {
  438. urlAnchor.href = s.url;
  439. // Support: IE8-11+
  440. // Anchor's host property isn't correctly set when s.url is relative
  441. urlAnchor.href = urlAnchor.href;
  442. s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
  443. urlAnchor.protocol + "//" + urlAnchor.host;
  444. } catch ( e ) {
  445. // If there is an error parsing the URL, assume it is crossDomain,
  446. // it can be rejected by the transport if it is invalid
  447. s.crossDomain = true;
  448. }
  449. }
  450. // Convert data if not already a string
  451. if ( s.data && s.processData && typeof s.data !== "string" ) {
  452. s.data = jQuery.param( s.data, s.traditional );
  453. }
  454. // Apply prefilters
  455. inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
  456. // If request was aborted inside a prefilter, stop there
  457. if ( state === 2 ) {
  458. return jqXHR;
  459. }
  460. // We can fire global events as of now if asked to
  461. // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
  462. fireGlobals = jQuery.event && s.global;
  463. // Watch for a new set of requests
  464. if ( fireGlobals && jQuery.active++ === 0 ) {
  465. jQuery.event.trigger( "ajaxStart" );
  466. }
  467. // Uppercase the type
  468. s.type = s.type.toUpperCase();
  469. // Determine if request has content
  470. s.hasContent = !rnoContent.test( s.type );
  471. // Save the URL in case we're toying with the If-Modified-Since
  472. // and/or If-None-Match header later on
  473. cacheURL = s.url;
  474. // More options handling for requests with no content
  475. if ( !s.hasContent ) {
  476. // If data is available, append data to url
  477. if ( s.data ) {
  478. cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
  479. // #9682: remove data so that it's not used in an eventual retry
  480. delete s.data;
  481. }
  482. // Add anti-cache in url if needed
  483. if ( s.cache === false ) {
  484. s.url = rts.test( cacheURL ) ?
  485. // If there is already a '_' parameter, set its value
  486. cacheURL.replace( rts, "$1_=" + nonce++ ) :
  487. // Otherwise add one to the end
  488. cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
  489. }
  490. }
  491. // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
  492. if ( s.ifModified ) {
  493. if ( jQuery.lastModified[ cacheURL ] ) {
  494. jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
  495. }
  496. if ( jQuery.etag[ cacheURL ] ) {
  497. jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
  498. }
  499. }
  500. // Set the correct header, if data is being sent
  501. if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
  502. jqXHR.setRequestHeader( "Content-Type", s.contentType );
  503. }
  504. // Set the Accepts header for the server, depending on the dataType
  505. jqXHR.setRequestHeader(
  506. "Accept",
  507. s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
  508. s.accepts[ s.dataTypes[ 0 ] ] +
  509. ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
  510. s.accepts[ "*" ]
  511. );
  512. // Check for headers option
  513. for ( i in s.headers ) {
  514. jqXHR.setRequestHeader( i, s.headers[ i ] );
  515. }
  516. // Allow custom headers/mimetypes and early abort
  517. if ( s.beforeSend &&
  518. ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
  519. // Abort if not done already and return
  520. return jqXHR.abort();
  521. }
  522. // Aborting is no longer a cancellation
  523. strAbort = "abort";
  524. // Install callbacks on deferreds
  525. for ( i in { success: 1, error: 1, complete: 1 } ) {
  526. jqXHR[ i ]( s[ i ] );
  527. }
  528. // Get transport
  529. transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
  530. // If no transport, we auto-abort
  531. if ( !transport ) {
  532. done( -1, "No Transport" );
  533. } else {
  534. jqXHR.readyState = 1;
  535. // Send global event
  536. if ( fireGlobals ) {
  537. globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
  538. }
  539. // If request was aborted inside ajaxSend, stop there
  540. if ( state === 2 ) {
  541. return jqXHR;
  542. }
  543. // Timeout
  544. if ( s.async && s.timeout > 0 ) {
  545. timeoutTimer = window.setTimeout( function() {
  546. jqXHR.abort( "timeout" );
  547. }, s.timeout );
  548. }
  549. try {
  550. state = 1;
  551. transport.send( requestHeaders, done );
  552. } catch ( e ) {
  553. // Propagate exception as error if not done
  554. if ( state < 2 ) {
  555. done( -1, e );
  556. // Simply rethrow otherwise
  557. } else {
  558. throw e;
  559. }
  560. }
  561. }
  562. // Callback for when everything is done
  563. function done( status, nativeStatusText, responses, headers ) {
  564. var isSuccess, success, error, response, modified,
  565. statusText = nativeStatusText;
  566. // Called once
  567. if ( state === 2 ) {
  568. return;
  569. }
  570. // State is "done" now
  571. state = 2;
  572. // Clear timeout if it exists
  573. if ( timeoutTimer ) {
  574. window.clearTimeout( timeoutTimer );
  575. }
  576. // Dereference transport for early garbage collection
  577. // (no matter how long the jqXHR object will be used)
  578. transport = undefined;
  579. // Cache response headers
  580. responseHeadersString = headers || "";
  581. // Set readyState
  582. jqXHR.readyState = status > 0 ? 4 : 0;
  583. // Determine if successful
  584. isSuccess = status >= 200 && status < 300 || status === 304;
  585. // Get response data
  586. if ( responses ) {
  587. response = ajaxHandleResponses( s, jqXHR, responses );
  588. }
  589. // Convert no matter what (that way responseXXX fields are always set)
  590. response = ajaxConvert( s, response, jqXHR, isSuccess );
  591. // If successful, handle type chaining
  592. if ( isSuccess ) {
  593. // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
  594. if ( s.ifModified ) {
  595. modified = jqXHR.getResponseHeader( "Last-Modified" );
  596. if ( modified ) {
  597. jQuery.lastModified[ cacheURL ] = modified;
  598. }
  599. modified = jqXHR.getResponseHeader( "etag" );
  600. if ( modified ) {
  601. jQuery.etag[ cacheURL ] = modified;
  602. }
  603. }
  604. // if no content
  605. if ( status === 204 || s.type === "HEAD" ) {
  606. statusText = "nocontent";
  607. // if not modified
  608. } else if ( status === 304 ) {
  609. statusText = "notmodified";
  610. // If we have data, let's convert it
  611. } else {
  612. statusText = response.state;
  613. success = response.data;
  614. error = response.error;
  615. isSuccess = !error;
  616. }
  617. } else {
  618. // Extract error from statusText and normalize for non-aborts
  619. error = statusText;
  620. if ( status || !statusText ) {
  621. statusText = "error";
  622. if ( status < 0 ) {
  623. status = 0;
  624. }
  625. }
  626. }
  627. // Set data for the fake xhr object
  628. jqXHR.status = status;
  629. jqXHR.statusText = ( nativeStatusText || statusText ) + "";
  630. // Success/Error
  631. if ( isSuccess ) {
  632. deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
  633. } else {
  634. deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
  635. }
  636. // Status-dependent callbacks
  637. jqXHR.statusCode( statusCode );
  638. statusCode = undefined;
  639. if ( fireGlobals ) {
  640. globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
  641. [ jqXHR, s, isSuccess ? success : error ] );
  642. }
  643. // Complete
  644. completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
  645. if ( fireGlobals ) {
  646. globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
  647. // Handle the global AJAX counter
  648. if ( !( --jQuery.active ) ) {
  649. jQuery.event.trigger( "ajaxStop" );
  650. }
  651. }
  652. }
  653. return jqXHR;
  654. },
  655. getJSON: function( url, data, callback ) {
  656. return jQuery.get( url, data, callback, "json" );
  657. },
  658. getScript: function( url, callback ) {
  659. return jQuery.get( url, undefined, callback, "script" );
  660. }
  661. } );
  662. jQuery.each( [ "get", "post" ], function( i, method ) {
  663. jQuery[ method ] = function( url, data, callback, type ) {
  664. // Shift arguments if data argument was omitted
  665. if ( jQuery.isFunction( data ) ) {
  666. type = type || callback;
  667. callback = data;
  668. data = undefined;
  669. }
  670. // The url can be an options object (which then must have .url)
  671. return jQuery.ajax( jQuery.extend( {
  672. url: url,
  673. type: method,
  674. dataType: type,
  675. data: data,
  676. success: callback
  677. }, jQuery.isPlainObject( url ) && url ) );
  678. };
  679. } );
  680. return jQuery;
  681. } );