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