/* Copyright (c) 2009, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 3.0.0 build: 1549 */ YUI.add('io-xdr', function(Y) { /** * Extends the IO base class to provide an alternate, Flash transport, for making * cross-domain requests. * @module io * @submodule io-xdr */ /** * @event io:xdrReady * @description This event is fired by YUI.io when the specified transport is * ready for use. * @type Event Custom */ var E_XDR_READY = 'io:xdrReady', /** * @description Object that stores callback handlers for cross-domain requests * when using Flash as the transport. * * @property _fn * @private * @static * @type object */ _fn = {}, /** * @description Map of transaction state used when XDomainRequest is the * XDR transport. * * @property _rS * @private * @static * @type object */ _rS = {}; /** * @description Method that creates the Flash transport swf. * * @method _swf * @private * @static * @param {string} uri - location of io.swf. * @param {string} yid - YUI instance id. * @return void */ function _swf(uri, yid) { var o = '' + '' + '' + '' + '', c = document.createElement('div'); document.body.appendChild(c); c.innerHTML = o; } /** * @description Sets event handlers for XDomainRequest transactions. * * @method _xdr * @private * @static * @param {object} o - Transaction object generated by _create() in io-base. * @param {object} c - configuration object for the transaction. * @return void */ function _xdr(o, c) { o.c.onprogress = function() { _rS[o.id] = 3; } o.c.onload = function() { _rS[o.id] = 4; Y.io.xdrResponse(o, c, 'success'); }; o.c.onerror = function() { _rS[o.id] = 4; Y.io.xdrResponse(o, c, 'failure'); }; if (c.timeout) { o.c.ontimeout = function() { _rS[o.id] = 4; Y.io.xdrResponse(o, c, 'timeout'); }; o.c.timeout = c.timeout; } } /** * @description Creates a response object for XDR transactions, for success * and failure cases. * * @method _data * @private * @static * @param {object} o - Transaction object generated by _create() in io-base. * @param {boolean} isFlash - True if Flash was used as the transport. * @param {boolean} isXML - True if the response data are XML. * * @return object */ function _data(o, isFlash, isXML) { var text, xml; if (!o.status) { text = isFlash ? decodeURI(o.c.responseText) : o.c.responseText; xml = isXML ? Y.DataType.XML.parse(text) : null; return { id: o.id, c: { responseText: text, responseXML: xml } }; } else { return { id: o.id, status: o.status }; } } /** * @description Method for intiating an XDR transaction abort. * * @method _abort * @private * @static * @param {object} o - Transaction object generated by _create() in io-base. * @param {object} c - configuration object for the transaction. */ function _abort(o, c) { return c.xdr.use === 'flash' ? o.c.abort(o.id, c) : o.c.abort(); } /** * @description Method for determining if an XDR transaction has completed * and all data are received. * * @method _isInProgress. * @private * @static * @param {object} o - Transaction object generated by _create() in io-base. * @param {object} c - configuration object for the transaction. */ function _isInProgress(o, t) { return (t === 'flash' && o.c) ? o.c.isInProgress(o.id) : _rS[o.id] !== 4; } Y.mix(Y.io, { /** * @description Map of io transports. * * @property _transport * @private * @static * @type object */ _transport: {}, /** * @description Method for accessing the transport's interface for making a * cross-domain transaction. * * @method _xdr * @private * @static * @param {string} uri - qualified path to transaction resource. * @param {object} o - Transaction object generated by _create() in io-base. * @param {object} c - configuration object for the transaction. */ xdr: function(uri, o, c) { if (c.on && c.xdr.use === 'flash') { _fn[o.id] = { on: c.on, context: c.context, arguments: c.arguments }; // These nodes do not need to be serialized across Flash's // ExternalInterface. Doing so will result in exceptions. c.context = null; c.form = null; o.c.send(uri, c, o.id); } else if (window.XDomainRequest) { _xdr(o, c); o.c.open(c.method || 'GET', uri); o.c.send(c.data); } return { id: o.id, abort: function() { return o.c ? _abort(o, c) : false; }, isInProgress: function() { return o.c ? _isInProgress(o, c.xdr.use) : false; } } }, /** * @description Response controller for cross-domain requests when using the * Flash transport or IE8's XDomainRequest object. * * @method xdrResponse * @private * @static * @param {object} o - Transaction object generated by _create() in io-base. * @param {object} c - configuration object for the transaction. * @param {string} e - Event name * @return object */ xdrResponse: function(o, c, e) { var m, fn, isFlash = c.xdr.use === 'flash' ? true : false, isXML = c.xdr.dataType === 'xml' ? true : false; c.on = c.on || {}; if (isFlash) { m = _fn || {}; fn = m[o.id] ? m[o.id] : null; if (fn) { c.on = fn.on; c.context = fn.context; c.arguments = fn.arguments; } } if (e === ('abort' || 'timeout')) { o.status = e; } switch (e) { case 'start': Y.io.start(o.id, c); break; case 'success': Y.io.success(_data(o, isFlash, isXML), c); isFlash ? delete m[o.id] : delete _rS[o.id]; break; case 'timeout': case 'abort': case 'failure': Y.io.failure(_data(o, isFlash, isXML), c); isFlash ? delete m[o.id] : delete _rS[o.id]; break; } }, /** * @description Fires event "io:xdrReady" * * @method xdrReady * @private * @static * @param {number} id - transaction id * @param {object} c - configuration object for the transaction. * * @return void */ xdrReady: function(id) { Y.fire(E_XDR_READY, id); }, /** * @description Method to initialize the desired transport. * * @method transport * @public * @static * @param {object} o - object of transport configurations. * @return void */ transport: function(o) { var id = o.yid ? o.yid : Y.id; _swf(o.src, id); this._transport.flash = Y.config.doc.getElementById('yuiIoSwf'); } }); }, '3.0.0' ,{requires:['io-base','datatype-xml']});