00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import <Foundation/CPObject.j>
00024
00025
00026 CPJSONPConnectionCallbacks = {};
00027
00028 CPJSONPCallbackReplacementString = @"${JSONP_CALLBACK}";
00029
00042 @implementation CPJSONPConnection : CPObject
00043 {
00044 CPURLRequest _request;
00045 id _delegate;
00046
00047 CPString _callbackParameter;
00048 DOMElement _scriptTag;
00049 }
00050
00052 + (CPJSONPConnection)sendRequest:(CPURLRequest)aRequest callback:(CPString)callbackParameter delegate:(id)aDelegate
00053 {
00054 return [self connectionWithRequest:aRequest callback:callbackParameter delegate:aDelegate];
00055 }
00056
00057 + (CPJSONPConnection)connectionWithRequest:(CPURLRequest)aRequest callback:(CPString)callbackParameter delegate:(id)aDelegate
00058 {
00059 return [[[self class] alloc] initWithRequest:aRequest callback:callbackParameter delegate:aDelegate startImmediately:YES];;
00060 }
00061
00062 - (id)initWithRequest:(CPURLRequest)aRequest callback:(CPString)aString delegate:(id)aDelegate
00063 {
00064 return [self initWithRequest:aRequest callback:aString delegate:aDelegate startImmediately: NO];
00065 }
00066
00067 - (id)initWithRequest:(CPURLRequest)aRequest callback:(CPString)aString delegate:(id)aDelegate startImmediately:(BOOL)shouldStartImmediately
00068 {
00069 self = [super init];
00070
00071 _request = aRequest;
00072 _delegate = aDelegate;
00073
00074 _callbackParameter = aString;
00075
00076 if (!_callbackParameter && [[_request URL] absoluteString].indexOf(CPJSONPCallbackReplacementString) < 0)
00077 [CPException raise:CPInvalidArgumentException reason:@"JSONP source specified without callback parameter or CPJSONPCallbackReplacementString in URL."];
00078
00079 if(shouldStartImmediately)
00080 [self start];
00081
00082 return self;
00083 }
00084
00085 - (void)start
00086 {
00087 try
00088 {
00089 CPJSONPConnectionCallbacks["callback"+[self UID]] = function(data)
00090 {
00091 [_delegate connection:self didReceiveData:data];
00092 [self removeScriptTag];
00093
00094 [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
00095 };
00096
00097 var head = document.getElementsByTagName("head").item(0),
00098 source = [[_request URL] absoluteString];
00099
00100 if (_callbackParameter)
00101 {
00102 source += (source.indexOf('?') < 0) ? "?" : "&";
00103 source += _callbackParameter+"=CPJSONPConnectionCallbacks.callback"+[self UID];
00104 }
00105 else if (source.indexOf(CPJSONPCallbackReplacementString) >= 0)
00106 {
00107 source = [source stringByReplacingOccurrencesOfString:CPJSONPCallbackReplacementString withString:"CPJSONPConnectionCallbacks.callback"+[self UID]];
00108 }
00109 else
00110 return;
00111
00112 _scriptTag = document.createElement("script");
00113 _scriptTag.setAttribute("type", "text/javascript");
00114 _scriptTag.setAttribute("charset", "utf-8");
00115 _scriptTag.setAttribute("src", source);
00116
00117 head.appendChild(_scriptTag);
00118 }
00119 catch (exception)
00120 {
00121 [_delegate connection: self didFailWithError: exception];
00122 [self removeScriptTag];
00123 }
00124 }
00125
00126 - (void)removeScriptTag
00127 {
00128 var head = document.getElementsByTagName("head").item(0);
00129
00130 if(_scriptTag && _scriptTag.parentNode == head)
00131 head.removeChild(_scriptTag);
00132
00133 CPJSONPConnectionCallbacks["callback"+[self UID]] = nil;
00134 delete CPJSONPConnectionCallbacks["callback"+[self UID]];
00135 }
00136
00137 - (void)cancel
00138 {
00139 [self removeScriptTag];
00140 }
00141
00142 @end