jsonp.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. define( [
  2. "../core",
  3. "../var/isFunction",
  4. "./var/nonce",
  5. "./var/rquery",
  6. "../ajax"
  7. ], function( jQuery, isFunction, nonce, rquery ) {
  8. "use strict";
  9. var oldCallbacks = [],
  10. rjsonp = /(=)\?(?=&|$)|\?\?/;
  11. // Default jsonp settings
  12. jQuery.ajaxSetup( {
  13. jsonp: "callback",
  14. jsonpCallback: function() {
  15. var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
  16. this[ callback ] = true;
  17. return callback;
  18. }
  19. } );
  20. // Detect, normalize options and install callbacks for jsonp requests
  21. jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
  22. var callbackName, overwritten, responseContainer,
  23. jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
  24. "url" :
  25. typeof s.data === "string" &&
  26. ( s.contentType || "" )
  27. .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
  28. rjsonp.test( s.data ) && "data"
  29. );
  30. // Handle iff the expected data type is "jsonp" or we have a parameter to set
  31. if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
  32. // Get callback name, remembering preexisting value associated with it
  33. callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ?
  34. s.jsonpCallback() :
  35. s.jsonpCallback;
  36. // Insert callback into url or form data
  37. if ( jsonProp ) {
  38. s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
  39. } else if ( s.jsonp !== false ) {
  40. s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
  41. }
  42. // Use data converter to retrieve json after script execution
  43. s.converters[ "script json" ] = function() {
  44. if ( !responseContainer ) {
  45. jQuery.error( callbackName + " was not called" );
  46. }
  47. return responseContainer[ 0 ];
  48. };
  49. // Force json dataType
  50. s.dataTypes[ 0 ] = "json";
  51. // Install callback
  52. overwritten = window[ callbackName ];
  53. window[ callbackName ] = function() {
  54. responseContainer = arguments;
  55. };
  56. // Clean-up function (fires after converters)
  57. jqXHR.always( function() {
  58. // If previous value didn't exist - remove it
  59. if ( overwritten === undefined ) {
  60. jQuery( window ).removeProp( callbackName );
  61. // Otherwise restore preexisting value
  62. } else {
  63. window[ callbackName ] = overwritten;
  64. }
  65. // Save back as free
  66. if ( s[ callbackName ] ) {
  67. // Make sure that re-using the options doesn't screw things around
  68. s.jsonpCallback = originalSettings.jsonpCallback;
  69. // Save the callback name for future use
  70. oldCallbacks.push( callbackName );
  71. }
  72. // Call if it was a function and we have a response
  73. if ( responseContainer && isFunction( overwritten ) ) {
  74. overwritten( responseContainer[ 0 ] );
  75. }
  76. responseContainer = overwritten = undefined;
  77. } );
  78. // Delegate to script
  79. return "script";
  80. }
  81. } );
  82. } );