Fixed a loop that only worked in webkit.
[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) 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( function(s) {
18         
19         var transportDataType = s.dataTypes[0];
20         
21         if ( s.jsonp ||
22                 transportDataType === "jsonp" ||
23                 transportDataType === "json" && ( jsre.test(s.url) || typeof(s.data) === "string" && jsre.test(s.data) ) ) {
24
25                 var jsonp = s.jsonp = s.jsonp || "callback",
26                         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 = url += (rquery_jsonp.test( url ) ? "&" : "?") + jsonp + "=" + jsonpCallback;
33                 }
34                 
35                 s.url = url;
36                 s.data = data;
37                 
38                 s.dataTypes[0] = "json";
39         }
40         
41 });
42
43 // Bind transport to json dataType
44 jQuery.xhr.bindTransport("json", function(s) {
45
46         if ( s.jsonp ) {
47                 
48                 // Put callback in place
49                 var responseContainer,
50                         jsonpCallback = s.jsonpCallback,
51                         previous = window[ jsonpCallback ];
52                         
53                 window [ jsonpCallback ] = function( response ) {
54                         responseContainer = [response];
55                 };
56                 
57                 s.complete = [function() {
58
59                         // Set callback back to previous value
60                         window[ jsonpCallback ] = previous;
61                         
62                         // Call if it was a function and we have a response
63                         if ( previous) {
64                                 if ( responseContainer && jQuery.isFunction ( previous ) ) {
65                                         window[ jsonpCallback ] ( responseContainer[0] );
66                                 }
67                         } else {
68                                 // else, more memory leak avoidance
69                                 try{ delete window[ jsonpCallback ]; } catch(e){}
70                         }
71                         
72                 }, s.complete ];
73                                 
74                 // Use data converter to retrieve json after script execution
75                 s.dataConverters["script => json"] = function() {
76                         if ( ! responseContainer ) {
77                                 jQuery.error("Callback '" + jsonpCallback + "' was not called");
78                         }
79                         return responseContainer[ 0 ];
80                 };
81                 
82                 // Delegate to script transport
83                 return "script";
84                 
85         }
86
87 });
88
89 })( jQuery );