a685bb19699b54b2167959c176fc2a953920f666
[jquery.git] / src / transports / jsonp.js
1 (function( jQuery ) {
2
3 var jsc = jQuery.now(),
4         jsre = /\=\?(&|$)/,
5         rquery_jsonp = /\?/;
6
7 // Default jsonp callback name
8 jQuery.ajaxSettings.jsonpCallback = function() {
9         return "jsonp" + jsc++;
10 };
11
12 // Normalize jsonp queries
13 // 1) put callback parameter in url or data
14 // 2) sneakily ensure transportDataType is json
15 // 3) ensure options jsonp is always provided so that jsonp requests are always
16 //    json request with the jsonp option set
17 jQuery.xhr.prefilter("json jsonp", function(s) {
18         
19         var transportDataType = s.dataTypes[ 0 ];
20         
21         s.dataTypes[ 0 ] = "json";
22         
23         if ( s.jsonp ||
24                 transportDataType === "jsonp" ||
25                 transportDataType === "json" && ( jsre.test(s.url) || typeof(s.data) === "string" && jsre.test(s.data) ) ) {
26
27                 var jsonp = s.jsonp = s.jsonp || "callback",
28                         jsonpCallback = s.jsonpCallback =
29                                 jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
30                         url = s.url.replace(jsre, "=" + jsonpCallback + "$1"),
31                         data = s.url == url && typeof(s.data) === "string" ? s.data.replace(jsre, "=" + jsonpCallback + "$1") : s.data;
32                         
33                 if ( url == s.url && data == s.data ) {
34                         url = url += (rquery_jsonp.test( url ) ? "&" : "?") + jsonp + "=" + jsonpCallback;
35                 }
36                 
37                 s.url = url;
38                 s.data = data;
39         }
40         
41 // Bind transport to json dataType
42 }).transport("json", function(s) {
43
44         if ( s.jsonp ) {
45                 
46                 // Put callback in place
47                 var responseContainer,
48                         jsonpCallback = s.jsonpCallback,
49                         previous = window[ jsonpCallback ];
50                         
51                 window [ jsonpCallback ] = function( response ) {
52                         responseContainer = [response];
53                 };
54                 
55                 s.complete = [function() {
56
57                         // Set callback back to previous value
58                         window[ jsonpCallback ] = previous;
59                         
60                         // Call if it was a function and we have a response
61                         if ( previous) {
62                                 if ( responseContainer && jQuery.isFunction ( previous ) ) {
63                                         window[ jsonpCallback ] ( responseContainer[0] );
64                                 }
65                         } else {
66                                 // else, more memory leak avoidance
67                                 try{ delete window[ jsonpCallback ]; } catch(e){}
68                         }
69                         
70                 }, s.complete ];
71                                 
72                 // Use data converter to retrieve json after script execution
73                 s.dataConverters["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
85 })( jQuery );