/** Socket.IO 0.6.3 - Built with build.js */ /** * socket.io-node-client * Copyright(c) 2011 LearnBoost * MIT Licensed */ /** * @namespace */ var io = this.io = { /** * Library version. */ version: '0.6.3', /** * Updates the location of the WebSocketMain.swf file that is required for the Flashsocket transport. * This should only be needed if you want to load in the WebSocketMainInsecure.swf or if you want to * host the .swf file on a other server. * * @static * @deprecated Set the variable `WEB_SOCKET_SWF_LOCATION` pointing to WebSocketMain.swf * @param {String} path The path of the .swf file * @api public */ setPath: function(path){ if (window.console && console.error) console.error('io.setPath will be removed. Please set the variable WEB_SOCKET_SWF_LOCATION pointing to WebSocketMain.swf'); this.path = /\/$/.test(path) ? path : path + '/'; WEB_SOCKET_SWF_LOCATION = path + 'lib/vendor/web-socket-js/WebSocketMain.swf'; } }; /** * Expose Socket.IO in jQuery */ if ('jQuery' in this) jQuery.io = this.io; /** * Default path to the .swf file. */ if (typeof window != 'undefined'){ // WEB_SOCKET_SWF_LOCATION = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//cdn.socket.io/' + this.io.version + '/WebSocketMain.swf'; if (typeof WEB_SOCKET_SWF_LOCATION === 'undefined') WEB_SOCKET_SWF_LOCATION = '/socket.io/lib/vendor/web-socket-js/WebSocketMain.swf'; } /** * socket.io-node-client * Copyright(c) 2011 LearnBoost * MIT Licensed */ (function(){ var io = this.io, /** * Set when the `onload` event is executed on the page. This variable is used by * `io.util.load` to detect if we need to execute the function immediately or add * it to a onload listener. * * @type {Boolean} * @api private */ pageLoaded = false; /** * @namespace */ io.util = { /** * Executes the given function when the page is loaded. * * Example: * * io.util.load(function(){ console.log('page loaded') }); * * @param {Function} fn * @api public */ load: function(fn){ if (/loaded|complete/.test(document.readyState) || pageLoaded) return fn(); if ('attachEvent' in window){ window.attachEvent('onload', fn); } else { window.addEventListener('load', fn, false); } }, /** * Defers the function untill it's the function can be executed without * blocking the load process. This is especially needed for WebKit based * browsers. If a long running connection is made before the onload event * a loading indicator spinner will be present at all times untill a * reconnect has been made. * * @param {Function} fn * @api public */ defer: function(fn){ if (!io.util.webkit) return fn(); io.util.load(function(){ setTimeout(fn,100); }); }, /** * Inherit the prototype methods from one constructor into another. * * Example: * * function foo(){}; * foo.prototype.hello = function(){ console.log( this.words )}; * * function bar(){ * this.words = "Hello world"; * }; * * io.util.inherit(bar,foo); * var person = new bar(); * person.hello(); * // => "Hello World" * * @param {Constructor} ctor The constructor that needs to inherit the methods. * @param {Constructor} superCtor The constructor to inherit from. * @api public */ inherit: function(ctor, superCtor){ // no support for `instanceof` for now for (var i in superCtor.prototype){ ctor.prototype[i] = superCtor.prototype[i]; } }, /** * Finds the index of item in a given Array. * * Example: * * var data = ['socket',2,3,4,'socket',5,6,7,'io']; * io.util.indexOf(data,'socket',1); * // => 4 * * @param {Array} arr The array * @param item The item that we need to find * @param {Integer} from Starting point * @api public */ indexOf: function(arr, item, from){ for (var l = arr.length, i = (from < 0) ? Math.max(0, l + from) : from || 0; i < l; i++){ if (arr[i] === item) return i; } return -1; }, /** * Checks if the given object is an Array. * * Example: * * io.util.isArray([]); * // => true * io.util.isArray({}); * // => false * * @param obj * @api public */ isArray: function(obj){ return Object.prototype.toString.call(obj) === '[object Array]'; }, /** * Merges the properties of two objects. * * Example: * * var a = {foo:'bar'} * , b = {bar:'baz'}; * * io.util.merge(a,b); * // => {foo:'bar',bar:'baz'} * * @param {Object} target The object that receives the keys * @param {Object} additional The object that supplies the keys * @api public */ merge: function(target, additional){ for (var i in additional) if (additional.hasOwnProperty(i)) target[i] = additional[i]; } }; /** * Detect the Webkit platform based on the userAgent string. * This includes Mobile Webkit. * * @type {Boolean} * @api public */ io.util.webkit = /webkit/i.test(navigator.userAgent); io.util.load(function(){ pageLoaded = true; }); })(); /** * socket.io-node-client * Copyright(c) 2011 LearnBoost * MIT Licensed */ (function(){ var io = this.io, /** * Message frame for encoding and decoding responses from the Socket.IO server. * * @const * @type {String} */ frame = '~m~', /** * Transforms the message to a string. If the message is an {Object} we will convert it to * a string and prefix it with the `~j~` flag to indicate that message is JSON encoded. * * Example: * * stringify({foo:"bar"}); * // => "~j~{"foo":"bar"}" * * @param {String|Array|Object} message The messages that needs to be transformed to a string. * @throws {Error} When the JSON.stringify implementation is missing in the browser. * @returns {String} Message. * @api private */ stringify = function(message){ if (Object.prototype.toString.call(message) == '[object Object]'){ if (!('JSON' in window)){ var error = 'Socket.IO Error: Trying to encode as JSON, but JSON.stringify is missing.'; if ('console' in window && console.error){ console.error(error); } else { throw new Error(error); } return '{ "$error": "'+ error +'" }'; } return '~j~' + JSON.stringify(message); } else { return String(message); } }, /** * This is the transport template for all supported transport methods. It provides the * basic functionality to create a working transport for Socket.IO. * * Options: * - `timeout` Transport shutdown timeout in milliseconds, based on the heartbeat interval. * * Example: * * var transport = io.Transport.mytransport = function(){ * io.Transport.apply(this, arguments); * }; * io.util.inherit(transport, io.Transport); * * ... // more code here * * // connect with your new transport * var socket = new io.Socket(null,{transports:['mytransport']}); * * @constructor * @param {Object} base The reference to io.Socket. * @param {Object} options The transport options. * @property {io.Socket|Object} base The reference to io.Socket. * @property {Object} options The transport options, these are used to overwrite the default options * @property {String} sessionid The sessionid of the established connection, this is only available a connection is established * @property {Boolean} connected The connection has been established. * @property {Boolean} connecting We are still connecting to the server. * @api public */ Transport = io.Transport = function(base, options){ this.base = base; this.options = { timeout: 15000 // based on heartbeat interval default }; io.util.merge(this.options, options); }; /** * Send the message to the connected Socket.IO server. * * @throws {Error} When the io.Transport is inherited, it should override this method. * @api public */ Transport.prototype.send = function(){ throw new Error('Missing send() implementation'); }; /** * Establish a connection with the Socket.IO server.. * * @throws {Error} When the io.Transport is inherited, it should override this method. * @api public */ Transport.prototype.connect = function(){ throw new Error('Missing connect() implementation'); }; /** * Disconnect the established connection. * * @throws {Error} When the io.Transport is inherited, it should override this method. * @api private */ Transport.prototype.disconnect = function(){ throw new Error('Missing disconnect() implementation'); }; /** * Encode the message by adding the `frame` to each message. This allows * the client so send multiple messages with only one request. * * @param {String|Array} messages Messages that need to be encoded. * @returns {String} Encoded message. * @api private */ Transport.prototype.encode = function(messages){ var ret = '', message; messages = io.util.isArray(messages) ? messages : [messages]; for (var i = 0, l = messages.length; i < l; i++){ message = messages[i] === null || messages[i] === undefined ? '' : stringify(messages[i]); ret += frame + message.length + frame + message; } return ret; }; /** * Decoded the response from the Socket.IO server, as the server could send multiple * messages in one response. * * @param (String} data The response from the server that requires decoding * @returns {Array} Decoded messages. * @api private */ Transport.prototype.decode = function(data){ var messages = [], number, n; do { if (data.substr(0, 3) !== frame) return messages; data = data.substr(3); number = '', n = ''; for (var i = 0, l = data.length; i < l; i++){ n = Number(data.substr(i, 1)); if (data.substr(i, 1) == n){ number += n; } else { data = data.substr(number.length + frame.length); number = Number(number); break; } } messages.push(data.substr(0, number)); // here data = data.substr(number); } while(data !== ''); return messages; }; /** * Handles the response from the server. When a new response is received * it will automatically update the timeout, decode the message and * forwards the response to the onMessage function for further processing. * * @param {String} data Response from the server. * @api private */ Transport.prototype.onData = function(data){ this.setTimeout(); var msgs = this.decode(data); if (msgs && msgs.length){ for (var i = 0, l = msgs.length; i < l; i++){ this.onMessage(msgs[i]); } } }; /** * All the transports have a dedicated timeout to detect if * the connection is still alive. We clear the existing timer * and set new one each time this function is called. When the * timeout does occur it will call the `onTimeout` method. * * @api private */ Transport.prototype.setTimeout = function(){ var self = this; if (this.timeout) clearTimeout(this.timeout); this.timeout = setTimeout(function(){ self.onTimeout(); }, this.options.timeout); }; /** * Disconnect from the Socket.IO server when a timeout occurs. * * @api private */ Transport.prototype.onTimeout = function(){ this.onDisconnect(); }; /** * After the response from the server has been parsed to individual * messages we need to decode them using the the Socket.IO message * protocol: . * * When a message is received we check if a session id has been set, * if the session id is missing we can assume that the received message * contains the sessionid of the connection. * When a message is prefixed with `~h~` we dispatch it our heartbeat * processing method `onHeartbeat` with the content of the heartbeat. * * When the message is prefixed with `~j~` we can assume that the contents * of the message is JSON encoded, so we parse the message and notify * the base of the new message. * * If none of the above, we consider it just a plain text message and * notify the base of the new message. * * @param {String} message A decoded message from the server. * @api private */ Transport.prototype.onMessage = function(message){ if (!this.sessionid){ this.sessionid = message; this.onConnect(); } else if (message.substr(0, 3) == '~h~'){ this.onHeartbeat(message.substr(3)); } else if (message.substr(0, 3) == '~j~'){ this.base.onMessage(JSON.parse(message.substr(3))); } else { this.base.onMessage(message); } }, /** * Send the received heartbeat message back to server. So the server * knows we are still connected. * * @param {String} heartbeat Heartbeat response from the server. * @api private */ Transport.prototype.onHeartbeat = function(heartbeat){ this.send('~h~' + heartbeat); // echo }; /** * Notifies the base when a connection to the Socket.IO server has * been established. And it starts the connection `timeout` timer. * * @api private */ Transport.prototype.onConnect = function(){ this.connected = true; this.connecting = false; this.base.onConnect(); this.setTimeout(); }; /** * Notifies the base when the connection with the Socket.IO server * has been disconnected. * * @api private */ Transport.prototype.onDisconnect = function(){ this.connecting = false; this.connected = false; this.sessionid = null; this.base.onDisconnect(); }; /** * Generates a connection url based on the Socket.IO URL Protocol. * See for more details. * * @returns {String} Connection url * @api private */ Transport.prototype.prepareUrl = function(){ return (this.base.options.secure ? 'https' : 'http') + '://' + this.base.host + ':' + this.base.options.port + '/' + this.base.options.resource + '/' + this.type + (this.sessionid ? ('/' + this.sessionid) : '/'); }; })(); /** * socket.io-node-client * Copyright(c) 2011 LearnBoost * MIT Licensed */ (function(){ var io = this.io, /** * A small stub function that will be used to reduce memory leaks. * * @type {Function} * @api private */ empty = new Function, /** * We preform a small feature detection to see if `Cross Origin Resource Sharing` * is supported in the `XMLHttpRequest` object, so we can use it for cross domain requests. * * @type {Boolean} * @api private */ XMLHttpRequestCORS = (function(){ if (!('XMLHttpRequest' in window)) return false; // CORS feature detection var a = new XMLHttpRequest(); return a.withCredentials != undefined; })(), /** * Generates the correct `XMLHttpRequest` for regular and cross domain requests. * * @param {Boolean} [xdomain] Create a request that can be used cross domain. * @returns {XMLHttpRequest|false} If we can create a XMLHttpRequest we will return that. * @api private */ request = function(xdomain){ if ('XDomainRequest' in window && xdomain) return new XDomainRequest(); if ('XMLHttpRequest' in window && (!xdomain || XMLHttpRequestCORS)) return new XMLHttpRequest(); if (!xdomain){ try { var a = new ActiveXObject('MSXML2.XMLHTTP'); return a; } catch(e){} try { var b = new ActiveXObject('Microsoft.XMLHTTP'); return b; } catch(e){} } return false; }, /** * This is the base for XHR based transports, the `XHR-Polling` and the `XHR-multipart` * transports will extend this class. * * @constructor * @extends {io.Transport} * @property {Array} sendBuffer Used to queue up messages so they can be send as one request. * @api public */ XHR = io.Transport.XHR = function(){ io.Transport.apply(this, arguments); this.sendBuffer = []; }; io.util.inherit(XHR, io.Transport); /** * Establish a connection * * @returns {Transport} * @api public */ XHR.prototype.connect = function(){ this.get(); return this; }; /** * Check if we need to send data to the Socket.IO server, if we have data in our buffer * we encode it and forward it to the sendIORequest method. * * @api private */ XHR.prototype.checkSend = function(){ if (!this.posting && this.sendBuffer.length){ var encoded = this.encode(this.sendBuffer); this.sendBuffer = []; this.sendIORequest(encoded); } }; /** * Send data to the Socket.IO server. * * @param data The message * @returns {Transport} * @api public */ XHR.prototype.send = function(data){ if (io.util.isArray(data)){ this.sendBuffer.push.apply(this.sendBuffer, data); } else { this.sendBuffer.push(data); } this.checkSend(); return this; }; /** * Posts a encoded message to the Socket.IO server. * * @param {String} data A encoded message. * @api private */ XHR.prototype.sendIORequest = function(data){ var self = this; this.posting = true; this.sendXHR = this.request('send', 'POST'); this.sendXHR.onreadystatechange = function(){ var status; if (self.sendXHR.readyState == 4){ self.sendXHR.onreadystatechange = empty; try { status = self.sendXHR.status; } catch(e){} self.posting = false; if (status == 200){ self.checkSend(); } else { self.onDisconnect(); } } }; this.sendXHR.send('data=' + encodeURIComponent(data)); }; /** * Disconnect the established connection. * * @returns {Transport}. * @api public */ XHR.prototype.disconnect = function(){ // send disconnection signal this.onDisconnect(); return this; }; /** * Handle the disconnect request. * * @api private */ XHR.prototype.onDisconnect = function(){ if (this.xhr){ this.xhr.onreadystatechange = empty; try { this.xhr.abort(); } catch(e){} this.xhr = null; } if (this.sendXHR){ this.sendXHR.onreadystatechange = empty; try { this.sendXHR.abort(); } catch(e){} this.sendXHR = null; } this.sendBuffer = []; io.Transport.prototype.onDisconnect.call(this); }; /** * Generates a configured XHR request * * @param {String} url The url that needs to be requested. * @param {String} method The method the request should use. * @param {Boolean} multipart Do a multipart XHR request * @returns {XMLHttpRequest} * @api private */ XHR.prototype.request = function(url, method, multipart){ var req = request(this.base.isXDomain()); if (multipart) req.multipart = true; req.open(method || 'GET', this.prepareUrl() + (url ? '/' + url : '')); if (method == 'POST' && 'setRequestHeader' in req){ req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=utf-8'); } return req; }; /** * Check if the XHR transports are supported * * @param {Boolean} xdomain Check if we support cross domain requests. * @returns {Boolean} * @api public */ XHR.check = function(xdomain){ try { if (request(xdomain)) return true; } catch(e){} return false; }; /** * Check if the XHR transport supports corss domain requests. * * @returns {Boolean} * @api public */ XHR.xdomainCheck = function(){ return XHR.check(true); }; XHR.request = request; })(); /** * socket.io-node-client * Copyright(c) 2011 LearnBoost * MIT Licensed */ (function(){ var io = this.io, /** * The WebSocket transport uses the HTML5 WebSocket API to establish an persistent * connection with the Socket.IO server. This transport will also be inherited by the * FlashSocket fallback as it provides a API compatible polyfill for the WebSockets. * * @constructor * @extends {io.Transport} * @api public */ WS = io.Transport.websocket = function(){ io.Transport.apply(this, arguments); }; io.util.inherit(WS, io.Transport); /** * The transport type, you use this to identify which transport was chosen. * * @type {String} * @api public */ WS.prototype.type = 'websocket'; /** * Initializes a new `WebSocket` connection with the Socket.IO server. We attach * all the appropriate listeners to handle the responses from the server. * * @returns {Transport} * @api public */ WS.prototype.connect = function(){ var self = this; this.socket = new WebSocket(this.prepareUrl()); this.socket.onmessage = function(ev){ self.onData(ev.data); }; this.socket.onclose = function(ev){ self.onDisconnect(); }; this.socket.onerror = function(e){ self.onError(e); }; return this; }; /** * Send a message to the Socket.IO server. The message will automatically be encoded * in the correct message format. * * @returns {Transport} * @api public */ WS.prototype.send = function(data){ if (this.socket) this.socket.send(this.encode(data)); return this; }; /** * Disconnect the established `WebSocket` connection. * * @returns {Transport} * @api public */ WS.prototype.disconnect = function(){ if (this.socket) this.socket.close(); return this; }; /** * Handle the errors that `WebSocket` might be giving when we * are attempting to connect or send messages. * * @param {Error} e The error. * @api private */ WS.prototype.onError = function(e){ this.base.emit('error', [e]); }; /** * Generate a `WebSocket` compatible URL based on the options * the user supplied in our Socket.IO base. * * @returns {String} Connection url * @api private */ WS.prototype.prepareUrl = function(){ return (this.base.options.secure ? 'wss' : 'ws') + '://' + this.base.host + ':' + this.base.options.port + '/' + this.base.options.resource + '/' + this.type + (this.sessionid ? ('/' + this.sessionid) : ''); }; /** * Checks if the browser has support for native `WebSockets` and that * it's not the polyfill created for the FlashSocket transport. * * @return {Boolean} * @api public */ WS.check = function(){ // we make sure WebSocket is not confounded with a previously loaded flash WebSocket return 'WebSocket' in window && WebSocket.prototype && ( WebSocket.prototype.send && !!WebSocket.prototype.send.toString().match(/native/i)) && typeof WebSocket !== "undefined"; }; /** * Check if the `WebSocket` transport support cross domain communications. * * @returns {Boolean} * @api public */ WS.xdomainCheck = function(){ return true; }; })(); /** * socket.io-node-client * Copyright(c) 2011 LearnBoost * MIT Licensed */ (function(){ var io = this.io, /** * The Flashsocket transport. This is a API wrapper for the HTML5 WebSocket specification. * It uses a .swf file to communicate with the server. If you want to serve the .swf file * from a other server than where the Socket.IO script is coming from you need to use the * insecure version of the .swf. More information about this can be found on the github page. * * @constructor * @extends {io.Transport.websocket} * @api public */ Flashsocket = io.Transport.flashsocket = function(){ io.Transport.websocket.apply(this, arguments); }; io.util.inherit(Flashsocket, io.Transport.websocket); /** * The transport type, you use this to identify which transport was chosen. * * @type {String} * @api public */ Flashsocket.prototype.type = 'flashsocket'; /** * Disconnect the established `Flashsocket` connection. This is done by adding a new * task to the Flashsocket. The rest will be handled off by the `WebSocket` transport. * * @returns {Transport} * @api public */ Flashsocket.prototype.connect = function(){ var self = this, args = arguments; WebSocket.__addTask(function(){ io.Transport.websocket.prototype.connect.apply(self, args); }); return this; }; /** * Sends a message to the Socket.IO server. This is done by adding a new * task to the Flashsocket. The rest will be handled off by the `WebSocket` transport. * * @returns {Transport} * @api public */ Flashsocket.prototype.send = function(){ var self = this, args = arguments; WebSocket.__addTask(function(){ io.Transport.websocket.prototype.send.apply(self, args); }); return this; }; /** * Check if the Flashsocket transport is supported as it requires that the Adobe Flash Player * plugin version `10.0.0` or greater is installed. And also check if the polyfill is correctly * loaded. * * @returns {Boolean} * @api public */ Flashsocket.check = function(){ if (typeof WebSocket == 'undefined' || !('__addTask' in WebSocket) || !swfobject) return false; return swfobject.hasFlashPlayerVersion("10.0.0"); }; /** * Check if the Flashsocket transport can be used as cross domain / cross origin transport. * Because we can't see which type (secure or insecure) of .swf is used we will just return true. * * @returns {Boolean} * @api public */ Flashsocket.xdomainCheck = function(){ return true; }; })(); /** * socket.io-node-client * Copyright(c) 2011 LearnBoost * MIT Licensed */ (function(){ var io = this.io, /** * The HTMLFile transport creates a `forever iframe` based transport * for Internet Explorer. Regular forever iframe implementations will * continuously trigger the browsers buzy indicators. If the forever iframe * is created inside a `htmlfile` these indicators will not be trigged. * * @constructor * @extends {io.Transport.XHR} * @api public */ HTMLFile = io.Transport.htmlfile = function(){ io.Transport.XHR.apply(this, arguments); }; io.util.inherit(HTMLFile, io.Transport.XHR); /** * The transport type, you use this to identify which transport was chosen. * * @type {String} * @api public */ HTMLFile.prototype.type = 'htmlfile'; /** * Starts the HTMLFile data stream for incoming messages. And registers a * onunload event listener so the HTMLFile will be destroyed. * * @api private */ HTMLFile.prototype.get = function(){ var self = this; this.open(); window.attachEvent('onunload', function(){ self.destroy(); }); }; /** * Creates a new ActiveX `htmlfile` with a forever loading iframe * that can be used to listen to messages. Inside the generated * `htmlfile` a reference will be made to the HTMLFile transport. * * @api private */ HTMLFile.prototype.open = function(){ this.doc = new ActiveXObject('htmlfile'); this.doc.open(); this.doc.write(''); this.doc.parentWindow.s = this; this.doc.close(); var iframeC = this.doc.createElement('div'); this.doc.body.appendChild(iframeC); this.iframe = this.doc.createElement('iframe'); iframeC.appendChild(this.iframe); this.iframe.src = this.prepareUrl() + '/' + (+ new Date); }; /** * The Socket.IO server will write script tags inside the forever * iframe, this function will be used as callback for the incoming * information. * * @param {String} data The message * @param {document} doc Reference to the context * @api private */ HTMLFile.prototype._ = function(data, doc){ this.onData(data); var script = doc.getElementsByTagName('script')[0]; script.parentNode.removeChild(script); }; /** * Destroy the established connection, iframe and `htmlfile`. * And calls the `CollectGarbage` function of Internet Explorer * to release the memory. * * @api private */ HTMLFile.prototype.destroy = function(){ if (this.iframe){ try { this.iframe.src = 'about:blank'; } catch(e){} this.doc = null; CollectGarbage(); } }; /** * Disconnects the established connection. * * @returns {Transport} Chaining. * @api public */ HTMLFile.prototype.disconnect = function(){ this.destroy(); return io.Transport.XHR.prototype.disconnect.call(this); }; /** * Checks if the browser supports this transport. The browser * must have an `ActiveXObject` implementation. * * @return {Boolean} * @api public */ HTMLFile.check = function(){ if ('ActiveXObject' in window){ try { var a = new ActiveXObject('htmlfile'); return a && io.Transport.XHR.check(); } catch(e){} } return false; }; /** * Check if cross domain requests are supported. * * @returns {Boolean} * @api public */ HTMLFile.xdomainCheck = function(){ // we can probably do handling for sub-domains, we should test that it's cross domain but a subdomain here return false; }; })(); /** * socket.io-node-client * Copyright(c) 2011 LearnBoost * MIT Licensed */ (function(){ var io = this.io, /** * The XHR-Multipart transport uses the a multipart XHR connection to * stream in the data from the Socket.IO server * * @constructor * @extends {io.Transport.XHR} * @api public */ XHRMultipart = io.Transport['xhr-multipart'] = function(){ io.Transport.XHR.apply(this, arguments); }; io.util.inherit(XHRMultipart, io.Transport.XHR); /** * The transport type, you use this to identify which transport was chosen. * * @type {String} * @api public */ XHRMultipart.prototype.type = 'xhr-multipart'; /** * Starts the multipart stream for incomming messages. * * @api private */ XHRMultipart.prototype.get = function(){ var self = this; this.xhr = this.request('', 'GET', true); this.xhr.onreadystatechange = function(){ if (self.xhr.readyState == 4) self.onData(self.xhr.responseText); }; this.xhr.send(null); }; /** * Checks if browser supports this transport. * * @return {Boolean} * @api public */ XHRMultipart.check = function(){ return 'XMLHttpRequest' in window && 'prototype' in XMLHttpRequest && 'multipart' in XMLHttpRequest.prototype; }; /** * Check if cross domain requests are supported. * * @returns {Boolean} * @api public */ XHRMultipart.xdomainCheck = function(){ return true; }; })(); /** * socket.io-node-client * Copyright(c) 2011 LearnBoost * MIT Licensed */ (function(){ var io = this.io, /** * A small stub function that will be used to reduce memory leaks. * * @type {Function} * @api private */ empty = new Function(), /** * The XHR-polling transport uses long polling XHR requests to create a * "persistent" connection with the server. * * @constructor * @extends {io.Transport.XHR} * @api public */ XHRPolling = io.Transport['xhr-polling'] = function(){ io.Transport.XHR.apply(this, arguments); }; io.util.inherit(XHRPolling, io.Transport.XHR); /** * The transport type, you use this to identify which transport was chosen. * * @type {string} * @api public */ XHRPolling.prototype.type = 'xhr-polling'; /** * Establish a connection, for iPhone and Android this will be done once the page * is loaded. * * @returns {Transport} Chaining. * @api public */ XHRPolling.prototype.connect = function(){ var self = this; io.util.defer(function(){ io.Transport.XHR.prototype.connect.call(self) }); return false; }; /** * Starts a XHR request to wait for incoming messages. * * @api private */ XHRPolling.prototype.get = function(){ var self = this; this.xhr = this.request(+ new Date, 'GET'); this.xhr.onreadystatechange = function(){ var status; if (self.xhr.readyState == 4){ self.xhr.onreadystatechange = empty; try { status = self.xhr.status; } catch(e){} if (status == 200){ self.onData(self.xhr.responseText); self.get(); } else { self.onDisconnect(); } } }; this.xhr.send(null); }; /** * Checks if browser supports this transport. * * @return {Boolean} * @api public */ XHRPolling.check = function(){ return io.Transport.XHR.check(); }; /** * Check if cross domain requests are supported * * @returns {Boolean} * @api public */ XHRPolling.xdomainCheck = function(){ return io.Transport.XHR.xdomainCheck(); }; })(); /** * socket.io-node-client * Copyright(c) 2011 LearnBoost * MIT Licensed */ (function(){ var io = this.io, /** * The JSONP transport creates an persistent connection by dynamically * inserting a script tag in the page. This script tag will receive the * information of the Socket.IO server. When new information is received * it creates a new script tag for the new data stream. * * @constructor * @extends {io.Transport.xhr-polling} * @api public */ JSONPPolling = io.Transport['jsonp-polling'] = function(){ io.Transport.XHR.apply(this, arguments); this.insertAt = document.getElementsByTagName('head')[0]; this.index = io.JSONP.length; io.JSONP.push(this); }; io.util.inherit(JSONPPolling, io.Transport['xhr-polling']); /** * A list of all JSONPolling transports, this is used for by * the Socket.IO server to distribute the callbacks. * * @type {Array} * @api private */ io.JSONP = []; /** * The transport type, you use this to identify which transport was chosen. * * @type {String} * @api public */ JSONPPolling.prototype.type = 'jsonp-polling'; /** * Posts a encoded message to the Socket.IO server using an iframe. * The iframe is used because script tags can create POST based requests. * The iframe is positioned outside of the view so the user does not * notice it's existence. * * @param {String} data A encoded message. * @api private */ JSONPPolling.prototype.sendIORequest = function(data){ var self = this; if (!('form' in this)){ var form = document.createElement('FORM'), area = document.createElement('TEXTAREA'), id = this.iframeId = 'socket_io_iframe_' + this.index, iframe; form.style.position = 'absolute'; form.style.top = '-1000px'; form.style.left = '-1000px'; form.target = id; form.method = 'POST'; form.action = this.prepareUrl() + '/' + (+new Date) + '/' + this.index; area.name = 'data'; form.appendChild(area); this.insertAt.insertBefore(form, null); document.body.appendChild(form); this.form = form; this.area = area; } function complete(){ initIframe(); self.posting = false; self.checkSend(); }; function initIframe(){ if (self.iframe){ self.form.removeChild(self.iframe); } try { // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) iframe = document.createElement('