text: 
  /**
   * socket.io
   * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
   * MIT Licensed
   */
  
  (function (exports, io, global) {
  
    /**
     * Expose constructor.
     */
  
    exports.Socket = Socket;
  
    /**
     * Create a new `Socket.IO client` which can establish a persistent
     * connection with a Socket.IO enabled server.
     *
     * @api public
     */
  
    function Socket (options) {
      this.options = {
          port: 80
        , secure: false
        , document: 'document' in global ? document : false
        , resource: 'socket.io'
        , transports: io.transports
        , 'connect timeout': 10000
        , 'try multiple transports': true
        , 'reconnect': true
        , 'reconnection delay': 500
        , 'reconnection limit': Infinity
        , 'reopen delay': 3000
        , 'max reconnection attempts': 10
        , 'sync disconnect on unload': true
        , 'auto connect': true
        , 'flash policy port': 10843
      };
  
      io.util.merge(this.options, options);
  
      this.connected = false;
      this.open = false;
      this.connecting = false;
      this.reconnecting = false;
      this.namespaces = {};
      this.buffer = [];
      this.doBuffer = false;
  
      if (this.options['sync disconnect on unload'] &&
          (!this.isXDomain() || io.util.ua.hasCORS)) {
        var self = this;
  
        io.util.on(global, 'beforeunload', function () {
          self.disconnectSync();
        }, false);
      }
  
      if (this.options['auto connect']) {
        this.connect();
      }
  };
  
    /**
     * Apply EventEmitter mixin.
     */
  
    io.util.mixin(Socket, io.EventEmitter);
  
    /**
     * Returns a namespace listener/emitter for this socket
     *
     * @api public
     */
  
    Socket.prototype.of = function (name) {
      if (!this.namespaces[name]) {
        this.namespaces[name] = new io.SocketNamespace(this, name);
  
        if (name !== '') {
          this.namespaces[name].packet({ type: 'connect' });
        }
      }
  
      return this.namespaces[name];
    };
  
    /**
     * Emits the given event to the Socket and all namespaces
     *
     * @api private
     */
  
    Socket.prototype.publish = function () {
      this.emit.apply(this, arguments);
  
      var nsp;
  
      for (var i in this.namespaces) {
        if (this.namespaces.hasOwnProperty(i)) {
          nsp = this.of(i);
          nsp.$emit.apply(nsp, arguments);
        }
      }
    };
  
    /**
     * Performs the handshake
     *
     * @api private
     */
  
    function empty () { };
  
    Socket.prototype.handshake = function (fn) {
      var self = this
        , options = this.options;
  
      function complete (data) {
        if (data instanceof Error) {
          self.onError(data.message);
        } else {
          fn.apply(null, data.split(':'));
        }
      };
  
      var url = [
            'http' + (options.secure ? 's' : '') + ':/'
          , options.host + ':' + options.port
          , options.resource
          , io.protocol
          , io.util.query(this.options.query, 't=' + +new Date)
        ].join('/');
  
      if (this.isXDomain() && !io.util.ua.hasCORS) {
        var insertAt = document.getElementsByTagName('script')[0]
          , script = document.createElement('script');
  
        script.src = url + '&jsonp=' + io.j.length;
        insertAt.parentNode.insertBefore(script, insertAt);
  
        io.j.push(function (data) {
          complete(data);
          script.parentNode.removeChild(script);
        });
      } else {
        var xhr = io.util.request();
  
        xhr.open('GET', url, true);
        xhr.onreadystatechange = function () {
          if (xhr.readyState == 4) {
            xhr.onreadystatechange = empty;
  
            if (xhr.status == 200) {
              complete(xhr.responseText);
            } else {
              !self.reconnecting && self.onError(xhr.responseText);
            }
          }
        };
        xhr.send(null);
      }
    };
  
    /**
     * Find an available transport based on the options supplied in the constructor.
     *
     * @api private
     */
  
    Socket.prototype.getTransport = function (override) {
      var transports = override || this.transports, match;
  
      for (var i = 0, transport; transport = transports[i]; i++) {
        if (io.Transport[transport]
          && io.Transport[transport].check(this)
          && (!this.isXDomain() || io.Transport[transport].xdomainCheck())) {
          return new io.Transport[transport](this, this.sessionid);
        }
      }
  
      return null;
    };
  
    /**
     * Connects to the server.
     *
     * @param {Function} [fn] Callback.
     * @returns {io.Socket}
     * @api public
     */
  
    Socket.prototype.connect = function (fn) {
      if (this.connecting) {
        return this;
      }
  
      var self = this;
  
      this.handshake(function (sid, heartbeat, close, transports) {
        self.sessionid = sid;
        self.closeTimeout = close * 1000;
        self.heartbeatTimeout = heartbeat * 1000;
        self.transports = io.util.intersect(
            transports.split(',')
          , self.options.transports
        );
  
        function connect (transports){
          if (self.transport) self.transport.clearTimeouts();
  
          self.transport = self.getTransport(transports);
          if (!self.transport) return self.publish('connect_failed');
  
          // once the transport is ready
          self.transport.ready(self, function () {
            self.connecting = true;
            self.publish('connecting', self.transport.name);
            self.transport.open();
  
            if (self.options['connect timeout']) {
              self.connectTimeoutTimer = setTimeout(function () {
                if (!self.connected) {
                  self.connecting = false;
  
                  if (self.options['try multiple transports']) {
                    if (!self.remainingTransports) {
                      self.remainingTransports = self.transports.slice(0);
                    }
  
                    var remaining = self.remainingTransports;
  
                    while (remaining.length > 0 && remaining.splice(0,1)[0] !=
                           self.transport.name) {}
  
                      if (remaining.length){
                        connect(remaining);
                      } else {
                        self.publish('connect_failed');
                      }
                  }
                }
              }, self.options['connect timeout']);
            }
          });
        }
  
        connect();
  
        self.once('connect', function (){
          clearTimeout(self.connectTimeoutTimer);
  
          fn && typeof fn == 'function' && fn();
        });
      });
  
      return this;
    };
  
    /**
     * Sends a message.
     *
     * @param {Object} data packet.
     * @returns {io.Socket}
     * @api public
     */
  
    Socket.prototype.packet = function (data) {
      if (this.connected && !this.doBuffer) {
        this.transport.packet(data);
      } else {
        this.buffer.push(data);
      }
  
      return this;
    };
  
    /**
     * Sets buffer state
     *
     * @api private
     */
  
    Socket.prototype.setBuffer = function (v) {
      this.doBuffer = v;
  
      if (!v && this.connected && this.buffer.length) {
        this.transport.payload(this.buffer);
        this.buffer = [];
      }
    };
  
    /**
     * Disconnect the established connect.
     *
     * @returns {io.Socket}
     * @api public
     */
  
    Socket.prototype.disconnect = function () {
      if (this.connected) {
        if (this.open) {
          this.of('').packet({ type: 'disconnect' });
        }
  
        // handle disconnection immediately
        this.onDisconnect('booted');
      }
  
      return this;
    };
  
    /**
     * Disconnects the socket with a sync XHR.
     *
     * @api private
     */
  
    Socket.prototype.disconnectSync = function () {
      // ensure disconnection
      var xhr = io.util.request()
        , uri = this.resource + '/' + io.protocol + '/' + this.sessionid;
  
      xhr.open('GET', uri, true);
  
      // handle disconnection immediately
      this.onDisconnect('booted');
    };
  
    /**
     * Check if we need to use cross domain enabled transports. Cross domain would
     * be a different port or different domain name.
     *
     * @returns {Boolean}
     * @api private
     */
  
    Socket.prototype.isXDomain = function () {
      // if node
      return false;
      // end node
  
      var port = global.location.port ||
        ('https:' == global.location.protocol ? 443 : 80);
  
      return this.options.host !== global.location.hostname 
        || this.options.port != port;
    };
  
    /**
     * Called upon handshake.
     *
     * @api private
     */
  
    Socket.prototype.onConnect = function () {
      if (!this.connected) {
        this.connected = true;
        this.connecting = false;
        if (!this.doBuffer) {
          // make sure to flush the buffer
          this.setBuffer(false);
        }
        this.emit('connect');
      }
    };
  
    /**
     * Called when the transport opens
     *
     * @api private
     */
  
    Socket.prototype.onOpen = function () {
      this.open = true;
    };
  
    /**
     * Called when the transport closes.
     *
     * @api private
     */
  
    Socket.prototype.onClose = function () {
      this.open = false;
    };
  
    /**
     * Called when the transport first opens a connection
     *
     * @param text
     */
  
    Socket.prototype.onPacket = function (packet) {
      this.of(packet.endpoint).onPacket(packet);
    };
  
    /**
     * Handles an error.
     *
     * @api private
     */
  
    Socket.prototype.onError = function (err) {
      if (err && err.advice) {
        if (err.advice === 'reconnect' && this.connected) {
          this.disconnect();
          this.reconnect();
        }
      }
  
      this.publish('error', err && err.reason ? err.reason : err);
    };
  
    /**
     * Called when the transport disconnects.
     *
     * @api private
     */
  
    Socket.prototype.onDisconnect = function (reason) {
      var wasConnected = this.connected;
  
      this.connected = false;
      this.connecting = false;
      this.open = false;
  
      if (wasConnected) {
        this.transport.close();
        this.transport.clearTimeouts();
        this.publish('disconnect', reason);
  
        if ('booted' != reason && this.options.reconnect && !this.reconnecting) {
          this.reconnect();
        }
      }
    };
  
    /**
     * Called upon reconnection.
     *
     * @api private
     */
  
    Socket.prototype.reconnect = function () {
      this.reconnecting = true;
      this.reconnectionAttempts = 0;
      this.reconnectionDelay = this.options['reconnection delay'];
  
      var self = this
        , maxAttempts = this.options['max reconnection attempts']
        , tryMultiple = this.options['try multiple transports']
        , limit = this.options['reconnection limit'];
  
      function reset () {
        if (self.connected) {
          for (var i in self.namespaces) {
            if (self.namespaces.hasOwnProperty(i) && '' !== i) {
                self.namespaces[i].packet({ type: 'connect' });
            }
          }
          self.publish('reconnect', self.transport.name, self.reconnectionAttempts);
        }
  
        self.removeListener('connect_failed', maybeReconnect);
        self.removeListener('connect', maybeReconnect);
  
        self.reconnecting = false;
  
        delete self.reconnectionAttempts;
        delete self.reconnectionDelay;
        delete self.reconnectionTimer;
        delete self.redoTransports;
  
        self.options['try multiple transports'] = tryMultiple;
      };
  
      function maybeReconnect () {
        if (!self.reconnecting) {
          return;
        }
  
        if (self.connected) {
          return reset();
        };
  
        if (self.connecting && self.reconnecting) {
          return self.reconnectionTimer = setTimeout(maybeReconnect, 1000);
        }
  
        if (self.reconnectionAttempts++ >= maxAttempts) {
          if (!self.redoTransports) {
            self.on('connect_failed', maybeReconnect);
            self.options['try multiple transports'] = true;
            self.transport = self.getTransport();
            self.redoTransports = true;
            self.connect();
          } else {
            self.publish('reconnect_failed');
            reset();
          }
        } else {
          if (self.reconnectionDelay < limit) {
            self.reconnectionDelay *= 2; // exponential back off
          }
  
          self.connect();
          self.publish('reconnecting', self.reconnectionDelay, self.reconnectionAttempts);
          self.reconnectionTimer = setTimeout(maybeReconnect, self.reconnectionDelay);
        }
      };
  
      this.options['try multiple transports'] = false;
      this.reconnectionTimer = setTimeout(maybeReconnect, this.reconnectionDelay);
  
      this.on('connect', maybeReconnect);
    };
  
  })(
      'undefined' != typeof io ? io : module.exports
    , 'undefined' != typeof io ? io : module.parent.exports
    , this
  );
  