API  1.0.0
CPJSONPConnection.j
Go to the documentation of this file.
1 /*
2  * CPJSONPConnection.j
3  * Foundation
4  *
5  * Created by Ross Boucher.
6  * Copyright 2008, 280 North, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 
25 
26 CPJSONPCallbackReplacementString = @"${JSONP_CALLBACK}";
27 
40 @implementation CPJSONPConnection : CPObject
41 {
42  CPURLRequest _request;
43  id _delegate;
44 
45  CPString _callbackParameter;
46  DOMElement _scriptTag;
47 }
48 
50 + (CPJSONPConnection)sendRequest:(CPURLRequest)aRequest callback:(CPString)callbackParameter delegate:(id)aDelegate
51 {
52  return [self connectionWithRequest:aRequest callback:callbackParameter delegate:aDelegate];
53 }
54 
55 + (CPJSONPConnection)connectionWithRequest:(CPURLRequest)aRequest callback:(CPString)callbackParameter delegate:(id)aDelegate
56 {
57  return [[[self class] alloc] initWithRequest:aRequest callback:callbackParameter delegate:aDelegate startImmediately:YES];
58 }
59 
60 - (id)initWithRequest:(CPURLRequest)aRequest callback:(CPString)aString delegate:(id)aDelegate
61 {
62  return [self initWithRequest:aRequest callback:aString delegate:aDelegate startImmediately: NO];
63 }
64 
65 - (id)initWithRequest:(CPURLRequest)aRequest callback:(CPString)aString delegate:(id)aDelegate startImmediately:(BOOL)shouldStartImmediately
66 {
67  self = [super init];
68 
69  if (self)
70  {
71  _request = aRequest;
72  _delegate = aDelegate;
73 
74  _callbackParameter = aString;
75 
76  if (!_callbackParameter && [[_request URL] absoluteString].indexOf(CPJSONPCallbackReplacementString) < 0)
77  [CPException raise:CPInvalidArgumentException reason:@"JSONP source specified without callback parameter or CPJSONPCallbackReplacementString in URL."];
78 
79  if (shouldStartImmediately)
80  [self start];
81  }
82 
83  return self;
84 }
85 
86 - (void)start
87 {
88  try
89  {
90  CPJSONPConnectionCallbacks["callback" + [self UID]] = function(data)
91  {
92  if ([_delegate respondsToSelector:@selector(connection:didReceiveData:)])
93  [_delegate connection:self didReceiveData:data];
94 
95  if ([_delegate respondsToSelector:@selector(connectionDidFinishLoading:)])
96  [_delegate connectionDidFinishLoading:self];
97 
98  [self removeScriptTag];
99 
100  [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
101  };
102 
103  var head = document.getElementsByTagName("head").item(0),
104  source = [[_request URL] absoluteString];
105 
106  if (_callbackParameter)
107  {
108  source += (source.indexOf('?') < 0) ? "?" : "&";
109  source += _callbackParameter + "=CPJSONPConnectionCallbacks.callback" + [self UID];
110  }
111  else if (source.indexOf(CPJSONPCallbackReplacementString) >= 0)
112  {
113  source = [source stringByReplacingOccurrencesOfString:CPJSONPCallbackReplacementString withString:"CPJSONPConnectionCallbacks.callback" + [self UID]];
114  }
115  else
116  return;
117 
118  _scriptTag = document.createElement("script");
119  _scriptTag.setAttribute("type", "text/javascript");
120  _scriptTag.setAttribute("charset", "utf-8");
121  _scriptTag.setAttribute("src", source);
122 
123  head.appendChild(_scriptTag);
124  }
125  catch (exception)
126  {
127  if ([_delegate respondsToSelector:@selector(connection:didFailWithError:)])
128  [_delegate connection: self didFailWithError: exception];
129 
130  [self removeScriptTag];
131  }
132 }
133 
134 - (void)removeScriptTag
135 {
136  var head = document.getElementsByTagName("head").item(0);
137 
138  if (_scriptTag && _scriptTag.parentNode == head)
139  head.removeChild(_scriptTag);
140 
141  CPJSONPConnectionCallbacks["callback" + [self UID]] = nil;
142  delete CPJSONPConnectionCallbacks["callback" + [self UID]];
143 }
144 
145 - (void)cancel
146 {
147  [self removeScriptTag];
148 }
149 
150 @end
Used to implement exception handling (creating & raising).
Definition: CPException.h:2
id initWithRequest:callback:delegate:startImmediately:(CPURLRequest aRequest, [callback] CPString aString, [delegate] id aDelegate, [startImmediately] BOOL shouldStartImmediately)
The main run loop for the application.
Definition: CPRunLoop.h:2
void raise:reason:(CPString aName, [reason] CPString aReason)
Definition: CPException.j:66
CPRunLoop currentRunLoop()
Definition: CPRunLoop.j:232
An immutable string (collection of characters).
Definition: CPString.h:2
CPJSONPCallbackReplacementString
Allows cross domain connections using JSONP protocol.
CPJSONPConnectionCallbacks
CPDate limitDateForMode:(CPString aMode)
Definition: CPRunLoop.j:342
id init()
Definition: CPObject.j:145
Contains data obtained during a request made with CPURLConnection.
Definition: CPURLRequest.h:2
FrameUpdater prototype start
var source
Class class()
Definition: CPObject.j:179
CPJSONPConnection connectionWithRequest:callback:delegate:(CPURLRequest aRequest, [callback] CPString callbackParameter, [delegate] id aDelegate)
CPString UID()
Definition: CPObject.j:552