f4b324e17c2155308e0b880598035b99f55be9eb
[jquery.git] / src / ajax / jsonp.js
1 (function( jQuery ) {
2
3 var jsc = jQuery.now(),
4         jsre = /\=(?:\?|%3F)(&|$)/i,
5         rquery_jsonp = /\?/;
6
7 // Default jsonp settings
8 jQuery.ajaxSetup({
9         jsonp: "callback",
10         jsonpCallback: function() {
11                 return "jsonp" + jsc++;
12         }
13 });
14
15 // Normalize jsonp queries
16 // 1) put callback parameter in url or data
17 // 2) sneakily ensure transportDataType is always jsonp for jsonp requests
18 jQuery.ajax.prefilter("json jsonp", function(s, originalSettings) {
19
20         if ( s.dataTypes[ 0 ] === "jsonp" ||
21                 originalSettings.jsonp ||
22                 originalSettings.jsonpCallback ||
23                 jsre.test(s.url) ||
24                 typeof(s.data) === "string" && jsre.test(s.data) ) {
25
26                 var jsonpCallback = s.jsonpCallback =
27                                 jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
28                         url = s.url.replace(jsre, "=" + jsonpCallback + "$1"),
29                         data = s.url === url && typeof(s.data) === "string" ? s.data.replace(jsre, "=" + jsonpCallback + "$1") : s.data;
30
31                 if ( url === s.url && data === s.data ) {
32                         url += (rquery_jsonp.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
33                 }
34
35                 s.url = url;
36                 s.data = data;
37                 s.dataTypes[ 0 ] = "jsonp";
38         }
39
40 // Bind transport to jsonp dataType
41 }).transport("jsonp", function(s) {
42
43         // Put callback in place
44         var responseContainer,
45                 jsonpCallback = s.jsonpCallback,
46                 previous = window[ jsonpCallback ];
47
48         window [ jsonpCallback ] = function( response ) {
49                 responseContainer = [response];
50         };
51
52         s.complete = [function() {
53
54                 // Set callback back to previous value
55                 window[ jsonpCallback ] = previous;
56
57                 // Call if it was a function and we have a response
58                 if ( previous) {
59                         if ( responseContainer && jQuery.isFunction ( previous ) ) {
60                                 window[ jsonpCallback ] ( responseContainer[0] );
61                         }
62                 } else {
63                         // else, more memory leak avoidance
64                         try{ delete window[ jsonpCallback ]; } catch(e){}
65                 }
66
67         }, s.complete ];
68
69         // Sneakily ensure this will be handled as json
70         s.dataTypes[ 0 ] = "json";
71
72         // Use data converter to retrieve json after script execution
73         s.converters["script json"] = function() {
74                 if ( ! responseContainer ) {
75                         jQuery.error( jsonpCallback + " was not called" );
76                 }
77                 return responseContainer[ 0 ];
78         };
79
80         // Delegate to script transport
81         return "script";
82 });
83
84 })( jQuery );