/** * socket.io * Copyright(c) 2011 LearnBoost * MIT Licensed */ (function (exports, io, global) { /** * Expose constructor. */ exports['xhr-polling'] = XHRPolling; /** * The XHR-polling transport uses long polling XHR requests to create a * "persistent" connection with the server. * * @constructor * @api public */ function XHRPolling () { io.Transport.XHR.apply(this, arguments); }; /** * Inherits from XHR transport. */ io.util.inherit(XHRPolling, io.Transport.XHR); /** * Merge the properties from XHR transport */ io.util.merge(XHRPolling, io.Transport.XHR); /** * Transport name * * @api public */ XHRPolling.prototype.name = 'xhr-polling'; /** * Indicates whether heartbeats is enabled for this transport * * @api private */ XHRPolling.prototype.heartbeats = function () { return false; }; /** * Establish a connection, for iPhone and Android this will be done once the page * is loaded. * * @returns {Transport} Chaining. * @api public */ XHRPolling.prototype.open = function () { var self = this; io.Transport.XHR.prototype.open.call(self); return false; }; /** * Starts a XHR request to wait for incoming messages. * * @api private */ function empty () {}; XHRPolling.prototype.get = function () { if (!this.isOpen) return; var self = this; function stateChange () { if (this.readyState == 4) { this.onreadystatechange = empty; if (this.status == 200) { self.onData(this.responseText); self.get(); } else { self.onClose(); } } }; function onload () { this.onload = empty; this.onerror = empty; self.retryCounter = 1; self.onData(this.responseText); self.get(); }; function onerror () { self.retryCounter ++; if(!self.retryCounter || self.retryCounter > 3) { self.onClose(); } else { self.get(); } }; this.xhr = this.request(); if (global.XDomainRequest && this.xhr instanceof XDomainRequest) { this.xhr.onload = onload; this.xhr.onerror = onerror; } else { this.xhr.onreadystatechange = stateChange; } this.xhr.send(null); }; /** * Handle the unclean close behavior. * * @api private */ XHRPolling.prototype.onClose = function () { io.Transport.XHR.prototype.onClose.call(this); if (this.xhr) { this.xhr.onreadystatechange = this.xhr.onload = this.xhr.onerror = empty; try { this.xhr.abort(); } catch(e){} this.xhr = null; } }; /** * Webkit based browsers show a infinit spinner when you start a XHR request * before the browsers onload event is called so we need to defer opening of * the transport until the onload event is called. Wrapping the cb in our * defer method solve this. * * @param {Socket} socket The socket instance that needs a transport * @param {Function} fn The callback * @api private */ XHRPolling.prototype.ready = function (socket, fn) { var self = this; io.util.defer(function () { fn.call(self); }); }; /** * Add the transport to your public io.transports array. * * @api private */ io.transports.push('xhr-polling'); })( 'undefined' != typeof io ? io.Transport : module.exports , 'undefined' != typeof io ? io : module.parent.exports , this );