|
1 YUI.add('io-xdr', function (Y, NAME) { |
|
2 |
|
3 /** |
|
4 Extends IO to provide an alternate, Flash transport, for making |
|
5 cross-domain requests. |
|
6 @module io |
|
7 @submodule io-xdr |
|
8 @for IO |
|
9 @deprecated |
|
10 **/ |
|
11 |
|
12 // Helpful resources when working with the mess that is XDomainRequest: |
|
13 // http://www.cypressnorth.com/blog/web-programming-and-development/internet-explorer-aborting-ajax-requests-fixed/ |
|
14 // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx |
|
15 |
|
16 /** |
|
17 Fires when the XDR transport is ready for use. |
|
18 @event io:xdrReady |
|
19 **/ |
|
20 var E_XDR_READY = Y.publish('io:xdrReady', { fireOnce: true }), |
|
21 |
|
22 /** |
|
23 Map of stored configuration objects when using |
|
24 Flash as the transport for cross-domain requests. |
|
25 |
|
26 @property _cB |
|
27 @private |
|
28 @type {Object} |
|
29 **/ |
|
30 _cB = {}, |
|
31 |
|
32 /** |
|
33 Map of transaction simulated readyState values |
|
34 when XDomainRequest is the transport. |
|
35 |
|
36 @property _rS |
|
37 @private |
|
38 @type {Object} |
|
39 **/ |
|
40 _rS = {}, |
|
41 |
|
42 // Document reference |
|
43 d = Y.config.doc, |
|
44 // Window reference |
|
45 w = Y.config.win, |
|
46 // XDomainRequest cross-origin request detection |
|
47 xdr = w && w.XDomainRequest; |
|
48 |
|
49 /** |
|
50 Method that creates the Flash transport swf. |
|
51 |
|
52 @method _swf |
|
53 @private |
|
54 @param {String} uri - location of io.swf. |
|
55 @param {String} yid - YUI sandbox id. |
|
56 @param {String} uid - IO instance id. |
|
57 **/ |
|
58 function _swf(uri, yid, uid) { |
|
59 var o = '<object id="io_swf" type="application/x-shockwave-flash" data="' + |
|
60 uri + '" width="0" height="0">' + |
|
61 '<param name="movie" value="' + uri + '">' + |
|
62 '<param name="FlashVars" value="yid=' + yid + '&uid=' + uid + '">' + |
|
63 '<param name="allowScriptAccess" value="always">' + |
|
64 '</object>', |
|
65 c = d.createElement('div'); |
|
66 |
|
67 d.body.appendChild(c); |
|
68 c.innerHTML = o; |
|
69 } |
|
70 |
|
71 /** |
|
72 Creates a response object for XDR transactions, for success |
|
73 and failure cases. |
|
74 |
|
75 @method _data |
|
76 @private |
|
77 @param {Object} o - Transaction object generated by _create() in io-base. |
|
78 @param {Boolean} u - Configuration xdr.use. |
|
79 @param {Boolean} d - Configuration xdr.dataType. |
|
80 |
|
81 @return {Object} |
|
82 **/ |
|
83 function _data(o, u, d) { |
|
84 if (u === 'flash') { |
|
85 o.c.responseText = decodeURI(o.c.responseText); |
|
86 } |
|
87 if (d === 'xml') { |
|
88 o.c.responseXML = Y.DataType.XML.parse(o.c.responseText); |
|
89 } |
|
90 |
|
91 return o; |
|
92 } |
|
93 |
|
94 /** |
|
95 Method for intiating an XDR transaction abort. |
|
96 |
|
97 @method _abort |
|
98 @private |
|
99 @param {Object} o - Transaction object generated by _create() in io-base. |
|
100 @param {Object} c - configuration object for the transaction. |
|
101 **/ |
|
102 function _abort(o, c) { |
|
103 return o.c.abort(o.id, c); |
|
104 } |
|
105 |
|
106 /** |
|
107 Method for determining if an XDR transaction has completed |
|
108 and all data are received. |
|
109 |
|
110 @method _isInProgress |
|
111 @private |
|
112 @param {Object} o - Transaction object generated by _create() in io-base. |
|
113 **/ |
|
114 function _isInProgress(o) { |
|
115 return xdr ? _rS[o.id] !== 4 : o.c.isInProgress(o.id); |
|
116 } |
|
117 |
|
118 Y.mix(Y.IO.prototype, { |
|
119 |
|
120 /** |
|
121 Map of io transports. |
|
122 |
|
123 @property _transport |
|
124 @private |
|
125 @type {Object} |
|
126 **/ |
|
127 _transport: {}, |
|
128 |
|
129 /** |
|
130 Sets event handlers for XDomainRequest transactions. |
|
131 |
|
132 @method _ieEvt |
|
133 @private |
|
134 @static |
|
135 @param {Object} o - Transaction object generated by _create() in io-base. |
|
136 @param {Object} c - configuration object for the transaction. |
|
137 **/ |
|
138 _ieEvt: function(o, c) { |
|
139 var io = this, |
|
140 i = o.id, |
|
141 t = 'timeout'; |
|
142 |
|
143 o.c.onprogress = function() { _rS[i] = 3; }; |
|
144 o.c.onload = function() { |
|
145 _rS[i] = 4; |
|
146 io.xdrResponse('success', o, c); |
|
147 }; |
|
148 o.c.onerror = function() { |
|
149 _rS[i] = 4; |
|
150 io.xdrResponse('failure', o, c); |
|
151 }; |
|
152 o.c.ontimeout = function() { |
|
153 _rS[i] = 4; |
|
154 io.xdrResponse(t, o, c); |
|
155 }; |
|
156 o.c[t] = c[t] || 0; |
|
157 }, |
|
158 |
|
159 /** |
|
160 Method for accessing the transport's interface for making a |
|
161 cross-domain transaction. |
|
162 |
|
163 @method xdr |
|
164 @param {String} uri - qualified path to transaction resource. |
|
165 @param {Object} o - Transaction object generated by _create() in io-base. |
|
166 @param {Object} c - configuration object for the transaction. |
|
167 **/ |
|
168 xdr: function(uri, o, c) { |
|
169 var io = this; |
|
170 |
|
171 if (c.xdr.use === 'flash') { |
|
172 // The configuration object cannot be serialized safely |
|
173 // across Flash's ExternalInterface. |
|
174 _cB[o.id] = c; |
|
175 w.setTimeout(function() { |
|
176 try { |
|
177 o.c.send(uri, { id: o.id, |
|
178 uid: o.uid, |
|
179 method: c.method, |
|
180 data: c.data, |
|
181 headers: c.headers }); |
|
182 } |
|
183 catch(e) { |
|
184 io.xdrResponse('transport error', o, c); |
|
185 delete _cB[o.id]; |
|
186 } |
|
187 }, Y.io.xdr.delay); |
|
188 } |
|
189 else if (xdr) { |
|
190 io._ieEvt(o, c); |
|
191 o.c.open(c.method || 'GET', uri); |
|
192 |
|
193 // Make async to protect against IE 8 oddities. |
|
194 setTimeout(function() { |
|
195 o.c.send(c.data); |
|
196 }, 0); |
|
197 } |
|
198 else { |
|
199 o.c.send(uri, o, c); |
|
200 } |
|
201 |
|
202 return { |
|
203 id: o.id, |
|
204 abort: function() { |
|
205 return o.c ? _abort(o, c) : false; |
|
206 }, |
|
207 isInProgress: function() { |
|
208 return o.c ? _isInProgress(o.id) : false; |
|
209 }, |
|
210 io: io |
|
211 }; |
|
212 }, |
|
213 |
|
214 /** |
|
215 Response controller for cross-domain requests when using the |
|
216 Flash transport or IE8's XDomainRequest object. |
|
217 |
|
218 @method xdrResponse |
|
219 @param {String} e Event name |
|
220 @param {Object} o Transaction object generated by _create() in io-base. |
|
221 @param {Object} c Configuration object for the transaction. |
|
222 @return {Object} |
|
223 **/ |
|
224 xdrResponse: function(e, o, c) { |
|
225 c = _cB[o.id] ? _cB[o.id] : c; |
|
226 var io = this, |
|
227 m = xdr ? _rS : _cB, |
|
228 u = c.xdr.use, |
|
229 d = c.xdr.dataType; |
|
230 |
|
231 switch (e) { |
|
232 case 'start': |
|
233 io.start(o, c); |
|
234 break; |
|
235 //case 'complete': |
|
236 //This case is not used by Flash or XDomainRequest. |
|
237 //io.complete(o, c); |
|
238 //break; |
|
239 case 'success': |
|
240 io.success(_data(o, u, d), c); |
|
241 delete m[o.id]; |
|
242 break; |
|
243 case 'timeout': |
|
244 case 'abort': |
|
245 case 'transport error': |
|
246 o.c = { status: 0, statusText: e }; |
|
247 case 'failure': |
|
248 io.failure(_data(o, u, d), c); |
|
249 delete m[o.id]; |
|
250 break; |
|
251 } |
|
252 }, |
|
253 |
|
254 /** |
|
255 Fires event "io:xdrReady" |
|
256 |
|
257 @method _xdrReady |
|
258 @private |
|
259 @param {Number} yid - YUI sandbox id. |
|
260 @param {Number} uid - IO instance id. |
|
261 **/ |
|
262 _xdrReady: function(yid, uid) { |
|
263 Y.fire(E_XDR_READY, yid, uid); |
|
264 }, |
|
265 |
|
266 /** |
|
267 Initializes the desired transport. |
|
268 |
|
269 @method transport |
|
270 @param {Object} o - object of transport configurations. |
|
271 **/ |
|
272 transport: function(c) { |
|
273 if (c.id === 'flash') { |
|
274 _swf(Y.UA.ie ? c.src + '?d=' + new Date().valueOf().toString() : c.src, Y.id, c.uid); |
|
275 Y.IO.transports.flash = function() { return d.getElementById('io_swf'); }; |
|
276 } |
|
277 } |
|
278 }); |
|
279 |
|
280 /** |
|
281 Fires event "io:xdrReady" |
|
282 |
|
283 @method xdrReady |
|
284 @protected |
|
285 @static |
|
286 @param {Number} yid - YUI sandbox id. |
|
287 @param {Number} uid - IO instance id. |
|
288 **/ |
|
289 Y.io.xdrReady = function(yid, uid){ |
|
290 var io = Y.io._map[uid]; |
|
291 Y.io.xdr.delay = 0; |
|
292 io._xdrReady.apply(io, [yid, uid]); |
|
293 }; |
|
294 |
|
295 Y.io.xdrResponse = function(e, o, c){ |
|
296 var io = Y.io._map[o.uid]; |
|
297 io.xdrResponse.apply(io, [e, o, c]); |
|
298 }; |
|
299 |
|
300 Y.io.transport = function(c){ |
|
301 var io = Y.io._map['io:0'] || new Y.IO(); |
|
302 c.uid = io._uid; |
|
303 io.transport.apply(io, [c]); |
|
304 }; |
|
305 |
|
306 /** |
|
307 Delay value to calling the Flash transport, in the |
|
308 event io.swf has not finished loading. Once the E_XDR_READY |
|
309 event is fired, this value will be set to 0. |
|
310 |
|
311 @property delay |
|
312 @static |
|
313 @type {Number} |
|
314 **/ |
|
315 Y.io.xdr = { delay : 100 }; |
|
316 |
|
317 |
|
318 }, '@VERSION@', {"requires": ["io-base", "datatype-xml-parse"]}); |