PageRenderTime 167ms CodeModel.GetById 88ms app.highlight 63ms RepoModel.GetById 1ms app.codeStats 1ms

/static/socket.io.js

https://bitbucket.org/nshetty/plotting-cpu-graph-in-near-real-time-with-gevent-socket.io
JavaScript | 3818 lines | 2872 code | 331 blank | 615 comment | 227 complexity | c0d95498ff96d63b2cbf520a5033d220 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*! Socket.IO.js build:0.9.6, development. Copyright(c) 2011 LearnBoost <dev@learnboost.com> MIT Licensed */
   2
   3var io = ('undefined' === typeof module ? {} : module.exports);
   4(function() {
   5
   6/**
   7 * socket.io
   8 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
   9 * MIT Licensed
  10 */
  11
  12(function (exports, global) {
  13
  14  /**
  15   * IO namespace.
  16   *
  17   * @namespace
  18   */
  19
  20  var io = exports;
  21
  22  /**
  23   * Socket.IO version
  24   *
  25   * @api public
  26   */
  27
  28  io.version = '0.9.6';
  29
  30  /**
  31   * Protocol implemented.
  32   *
  33   * @api public
  34   */
  35
  36  io.protocol = 1;
  37
  38  /**
  39   * Available transports, these will be populated with the available transports
  40   *
  41   * @api public
  42   */
  43
  44  io.transports = [];
  45
  46  /**
  47   * Keep track of jsonp callbacks.
  48   *
  49   * @api private
  50   */
  51
  52  io.j = [];
  53
  54  /**
  55   * Keep track of our io.Sockets
  56   *
  57   * @api private
  58   */
  59  io.sockets = {};
  60
  61
  62  /**
  63   * Manages connections to hosts.
  64   *
  65   * @param {String} uri
  66   * @Param {Boolean} force creation of new socket (defaults to false)
  67   * @api public
  68   */
  69
  70  io.connect = function (host, details) {
  71    var uri = io.util.parseUri(host)
  72      , uuri
  73      , socket;
  74
  75    if (global && global.location) {
  76      uri.protocol = uri.protocol || global.location.protocol.slice(0, -1);
  77      uri.host = uri.host || (global.document
  78        ? global.document.domain : global.location.hostname);
  79      uri.port = uri.port || global.location.port;
  80    }
  81
  82    uuri = io.util.uniqueUri(uri);
  83
  84    var options = {
  85        host: uri.host
  86      , secure: 'https' == uri.protocol
  87      , port: uri.port || ('https' == uri.protocol ? 443 : 80)
  88      , query: uri.query || ''
  89    };
  90
  91    io.util.merge(options, details);
  92
  93    if (options['force new connection'] || !io.sockets[uuri]) {
  94      socket = new io.Socket(options);
  95    }
  96
  97    if (!options['force new connection'] && socket) {
  98      io.sockets[uuri] = socket;
  99    }
 100
 101    socket = socket || io.sockets[uuri];
 102
 103    // if path is different from '' or /
 104    return socket.of(uri.path.length > 1 ? uri.path : '');
 105  };
 106
 107})('object' === typeof module ? module.exports : (this.io = {}), this);
 108/**
 109 * socket.io
 110 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 111 * MIT Licensed
 112 */
 113
 114(function (exports, global) {
 115
 116  /**
 117   * Utilities namespace.
 118   *
 119   * @namespace
 120   */
 121
 122  var util = exports.util = {};
 123
 124  /**
 125   * Parses an URI
 126   *
 127   * @author Steven Levithan <stevenlevithan.com> (MIT license)
 128   * @api public
 129   */
 130
 131  var re = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
 132
 133  var parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password',
 134               'host', 'port', 'relative', 'path', 'directory', 'file', 'query',
 135               'anchor'];
 136
 137  util.parseUri = function (str) {
 138    var m = re.exec(str || '')
 139      , uri = {}
 140      , i = 14;
 141
 142    while (i--) {
 143      uri[parts[i]] = m[i] || '';
 144    }
 145
 146    return uri;
 147  };
 148
 149  /**
 150   * Produces a unique url that identifies a Socket.IO connection.
 151   *
 152   * @param {Object} uri
 153   * @api public
 154   */
 155
 156  util.uniqueUri = function (uri) {
 157    var protocol = uri.protocol
 158      , host = uri.host
 159      , port = uri.port;
 160
 161    if ('document' in global) {
 162      host = host || document.domain;
 163      port = port || (protocol == 'https'
 164        && document.location.protocol !== 'https:' ? 443 : document.location.port);
 165    } else {
 166      host = host || 'localhost';
 167
 168      if (!port && protocol == 'https') {
 169        port = 443;
 170      }
 171    }
 172
 173    return (protocol || 'http') + '://' + host + ':' + (port || 80);
 174  };
 175
 176  /**
 177   * Mergest 2 query strings in to once unique query string
 178   *
 179   * @param {String} base
 180   * @param {String} addition
 181   * @api public
 182   */
 183
 184  util.query = function (base, addition) {
 185    var query = util.chunkQuery(base || '')
 186      , components = [];
 187
 188    util.merge(query, util.chunkQuery(addition || ''));
 189    for (var part in query) {
 190      if (query.hasOwnProperty(part)) {
 191        components.push(part + '=' + query[part]);
 192      }
 193    }
 194
 195    return components.length ? '?' + components.join('&') : '';
 196  };
 197
 198  /**
 199   * Transforms a querystring in to an object
 200   *
 201   * @param {String} qs
 202   * @api public
 203   */
 204
 205  util.chunkQuery = function (qs) {
 206    var query = {}
 207      , params = qs.split('&')
 208      , i = 0
 209      , l = params.length
 210      , kv;
 211
 212    for (; i < l; ++i) {
 213      kv = params[i].split('=');
 214      if (kv[0]) {
 215        query[kv[0]] = kv[1];
 216      }
 217    }
 218
 219    return query;
 220  };
 221
 222  /**
 223   * Executes the given function when the page is loaded.
 224   *
 225   *     io.util.load(function () { console.log('page loaded'); });
 226   *
 227   * @param {Function} fn
 228   * @api public
 229   */
 230
 231  var pageLoaded = false;
 232
 233  util.load = function (fn) {
 234    if ('document' in global && document.readyState === 'complete' || pageLoaded) {
 235      return fn();
 236    }
 237
 238    util.on(global, 'load', fn, false);
 239  };
 240
 241  /**
 242   * Adds an event.
 243   *
 244   * @api private
 245   */
 246
 247  util.on = function (element, event, fn, capture) {
 248    if (element.attachEvent) {
 249      element.attachEvent('on' + event, fn);
 250    } else if (element.addEventListener) {
 251      element.addEventListener(event, fn, capture);
 252    }
 253  };
 254
 255  /**
 256   * Generates the correct `XMLHttpRequest` for regular and cross domain requests.
 257   *
 258   * @param {Boolean} [xdomain] Create a request that can be used cross domain.
 259   * @returns {XMLHttpRequest|false} If we can create a XMLHttpRequest.
 260   * @api private
 261   */
 262
 263  util.request = function (xdomain) {
 264
 265    if (xdomain && 'undefined' != typeof XDomainRequest) {
 266      return new XDomainRequest();
 267    }
 268
 269    if ('undefined' != typeof XMLHttpRequest && (!xdomain || util.ua.hasCORS)) {
 270      return new XMLHttpRequest();
 271    }
 272
 273    if (!xdomain) {
 274      try {
 275        return new window[(['Active'].concat('Object').join('X'))]('Microsoft.XMLHTTP');
 276      } catch(e) { }
 277    }
 278
 279    return null;
 280  };
 281
 282  /**
 283   * XHR based transport constructor.
 284   *
 285   * @constructor
 286   * @api public
 287   */
 288
 289  /**
 290   * Change the internal pageLoaded value.
 291   */
 292
 293  if ('undefined' != typeof window) {
 294    util.load(function () {
 295      pageLoaded = true;
 296    });
 297  }
 298
 299  /**
 300   * Defers a function to ensure a spinner is not displayed by the browser
 301   *
 302   * @param {Function} fn
 303   * @api public
 304   */
 305
 306  util.defer = function (fn) {
 307    if (!util.ua.webkit || 'undefined' != typeof importScripts) {
 308      return fn();
 309    }
 310
 311    util.load(function () {
 312      setTimeout(fn, 100);
 313    });
 314  };
 315
 316  /**
 317   * Merges two objects.
 318   *
 319   * @api public
 320   */
 321  
 322  util.merge = function merge (target, additional, deep, lastseen) {
 323    var seen = lastseen || []
 324      , depth = typeof deep == 'undefined' ? 2 : deep
 325      , prop;
 326
 327    for (prop in additional) {
 328      if (additional.hasOwnProperty(prop) && util.indexOf(seen, prop) < 0) {
 329        if (typeof target[prop] !== 'object' || !depth) {
 330          target[prop] = additional[prop];
 331          seen.push(additional[prop]);
 332        } else {
 333          util.merge(target[prop], additional[prop], depth - 1, seen);
 334        }
 335      }
 336    }
 337
 338    return target;
 339  };
 340
 341  /**
 342   * Merges prototypes from objects
 343   *
 344   * @api public
 345   */
 346  
 347  util.mixin = function (ctor, ctor2) {
 348    util.merge(ctor.prototype, ctor2.prototype);
 349  };
 350
 351  /**
 352   * Shortcut for prototypical and static inheritance.
 353   *
 354   * @api private
 355   */
 356
 357  util.inherit = function (ctor, ctor2) {
 358    function f() {};
 359    f.prototype = ctor2.prototype;
 360    ctor.prototype = new f;
 361  };
 362
 363  /**
 364   * Checks if the given object is an Array.
 365   *
 366   *     io.util.isArray([]); // true
 367   *     io.util.isArray({}); // false
 368   *
 369   * @param Object obj
 370   * @api public
 371   */
 372
 373  util.isArray = Array.isArray || function (obj) {
 374    return Object.prototype.toString.call(obj) === '[object Array]';
 375  };
 376
 377  /**
 378   * Intersects values of two arrays into a third
 379   *
 380   * @api public
 381   */
 382
 383  util.intersect = function (arr, arr2) {
 384    var ret = []
 385      , longest = arr.length > arr2.length ? arr : arr2
 386      , shortest = arr.length > arr2.length ? arr2 : arr;
 387
 388    for (var i = 0, l = shortest.length; i < l; i++) {
 389      if (~util.indexOf(longest, shortest[i]))
 390        ret.push(shortest[i]);
 391    }
 392
 393    return ret;
 394  }
 395
 396  /**
 397   * Array indexOf compatibility.
 398   *
 399   * @see bit.ly/a5Dxa2
 400   * @api public
 401   */
 402
 403  util.indexOf = function (arr, o, i) {
 404    
 405    for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0; 
 406         i < j && arr[i] !== o; i++) {}
 407
 408    return j <= i ? -1 : i;
 409  };
 410
 411  /**
 412   * Converts enumerables to array.
 413   *
 414   * @api public
 415   */
 416
 417  util.toArray = function (enu) {
 418    var arr = [];
 419
 420    for (var i = 0, l = enu.length; i < l; i++)
 421      arr.push(enu[i]);
 422
 423    return arr;
 424  };
 425
 426  /**
 427   * UA / engines detection namespace.
 428   *
 429   * @namespace
 430   */
 431
 432  util.ua = {};
 433
 434  /**
 435   * Whether the UA supports CORS for XHR.
 436   *
 437   * @api public
 438   */
 439
 440  util.ua.hasCORS = 'undefined' != typeof XMLHttpRequest && (function () {
 441    try {
 442      var a = new XMLHttpRequest();
 443    } catch (e) {
 444      return false;
 445    }
 446
 447    return a.withCredentials != undefined;
 448  })();
 449
 450  /**
 451   * Detect webkit.
 452   *
 453   * @api public
 454   */
 455
 456  util.ua.webkit = 'undefined' != typeof navigator
 457    && /webkit/i.test(navigator.userAgent);
 458
 459   /**
 460   * Detect iPad/iPhone/iPod.
 461   *
 462   * @api public
 463   */
 464
 465  util.ua.iDevice = 'undefined' != typeof navigator
 466      && /iPad|iPhone|iPod/i.test(navigator.userAgent);
 467
 468})('undefined' != typeof io ? io : module.exports, this);
 469
 470/**
 471 * socket.io
 472 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 473 * MIT Licensed
 474 */
 475
 476(function (exports, io) {
 477
 478  /**
 479   * Expose constructor.
 480   */
 481
 482  exports.EventEmitter = EventEmitter;
 483
 484  /**
 485   * Event emitter constructor.
 486   *
 487   * @api public.
 488   */
 489
 490  function EventEmitter () {};
 491
 492  /**
 493   * Adds a listener
 494   *
 495   * @api public
 496   */
 497
 498  EventEmitter.prototype.on = function (name, fn) {
 499    if (!this.$events) {
 500      this.$events = {};
 501    }
 502
 503    if (!this.$events[name]) {
 504      this.$events[name] = fn;
 505    } else if (io.util.isArray(this.$events[name])) {
 506      this.$events[name].push(fn);
 507    } else {
 508      this.$events[name] = [this.$events[name], fn];
 509    }
 510
 511    return this;
 512  };
 513
 514  EventEmitter.prototype.addListener = EventEmitter.prototype.on;
 515
 516  /**
 517   * Adds a volatile listener.
 518   *
 519   * @api public
 520   */
 521
 522  EventEmitter.prototype.once = function (name, fn) {
 523    var self = this;
 524
 525    function on () {
 526      self.removeListener(name, on);
 527      fn.apply(this, arguments);
 528    };
 529
 530    on.listener = fn;
 531    this.on(name, on);
 532
 533    return this;
 534  };
 535
 536  /**
 537   * Removes a listener.
 538   *
 539   * @api public
 540   */
 541
 542  EventEmitter.prototype.removeListener = function (name, fn) {
 543    if (this.$events && this.$events[name]) {
 544      var list = this.$events[name];
 545
 546      if (io.util.isArray(list)) {
 547        var pos = -1;
 548
 549        for (var i = 0, l = list.length; i < l; i++) {
 550          if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
 551            pos = i;
 552            break;
 553          }
 554        }
 555
 556        if (pos < 0) {
 557          return this;
 558        }
 559
 560        list.splice(pos, 1);
 561
 562        if (!list.length) {
 563          delete this.$events[name];
 564        }
 565      } else if (list === fn || (list.listener && list.listener === fn)) {
 566        delete this.$events[name];
 567      }
 568    }
 569
 570    return this;
 571  };
 572
 573  /**
 574   * Removes all listeners for an event.
 575   *
 576   * @api public
 577   */
 578
 579  EventEmitter.prototype.removeAllListeners = function (name) {
 580    // TODO: enable this when node 0.5 is stable
 581    //if (name === undefined) {
 582      //this.$events = {};
 583      //return this;
 584    //}
 585
 586    if (this.$events && this.$events[name]) {
 587      this.$events[name] = null;
 588    }
 589
 590    return this;
 591  };
 592
 593  /**
 594   * Gets all listeners for a certain event.
 595   *
 596   * @api publci
 597   */
 598
 599  EventEmitter.prototype.listeners = function (name) {
 600    if (!this.$events) {
 601      this.$events = {};
 602    }
 603
 604    if (!this.$events[name]) {
 605      this.$events[name] = [];
 606    }
 607
 608    if (!io.util.isArray(this.$events[name])) {
 609      this.$events[name] = [this.$events[name]];
 610    }
 611
 612    return this.$events[name];
 613  };
 614
 615  /**
 616   * Emits an event.
 617   *
 618   * @api public
 619   */
 620
 621  EventEmitter.prototype.emit = function (name) {
 622    if (!this.$events) {
 623      return false;
 624    }
 625
 626    var handler = this.$events[name];
 627
 628    if (!handler) {
 629      return false;
 630    }
 631
 632    var args = Array.prototype.slice.call(arguments, 1);
 633
 634    if ('function' == typeof handler) {
 635      handler.apply(this, args);
 636    } else if (io.util.isArray(handler)) {
 637      var listeners = handler.slice();
 638
 639      for (var i = 0, l = listeners.length; i < l; i++) {
 640        listeners[i].apply(this, args);
 641      }
 642    } else {
 643      return false;
 644    }
 645
 646    return true;
 647  };
 648
 649})(
 650    'undefined' != typeof io ? io : module.exports
 651  , 'undefined' != typeof io ? io : module.parent.exports
 652);
 653
 654/**
 655 * socket.io
 656 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 657 * MIT Licensed
 658 */
 659
 660/**
 661 * Based on JSON2 (http://www.JSON.org/js.html).
 662 */
 663
 664(function (exports, nativeJSON) {
 665  "use strict";
 666
 667  // use native JSON if it's available
 668  if (nativeJSON && nativeJSON.parse){
 669    return exports.JSON = {
 670      parse: nativeJSON.parse
 671    , stringify: nativeJSON.stringify
 672    }
 673  }
 674
 675  var JSON = exports.JSON = {};
 676
 677  function f(n) {
 678      // Format integers to have at least two digits.
 679      return n < 10 ? '0' + n : n;
 680  }
 681
 682  function date(d, key) {
 683    return isFinite(d.valueOf()) ?
 684        d.getUTCFullYear()     + '-' +
 685        f(d.getUTCMonth() + 1) + '-' +
 686        f(d.getUTCDate())      + 'T' +
 687        f(d.getUTCHours())     + ':' +
 688        f(d.getUTCMinutes())   + ':' +
 689        f(d.getUTCSeconds())   + 'Z' : null;
 690  };
 691
 692  var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
 693      escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
 694      gap,
 695      indent,
 696      meta = {    // table of character substitutions
 697          '\b': '\\b',
 698          '\t': '\\t',
 699          '\n': '\\n',
 700          '\f': '\\f',
 701          '\r': '\\r',
 702          '"' : '\\"',
 703          '\\': '\\\\'
 704      },
 705      rep;
 706
 707
 708  function quote(string) {
 709
 710// If the string contains no control characters, no quote characters, and no
 711// backslash characters, then we can safely slap some quotes around it.
 712// Otherwise we must also replace the offending characters with safe escape
 713// sequences.
 714
 715      escapable.lastIndex = 0;
 716      return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
 717          var c = meta[a];
 718          return typeof c === 'string' ? c :
 719              '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
 720      }) + '"' : '"' + string + '"';
 721  }
 722
 723
 724  function str(key, holder) {
 725
 726// Produce a string from holder[key].
 727
 728      var i,          // The loop counter.
 729          k,          // The member key.
 730          v,          // The member value.
 731          length,
 732          mind = gap,
 733          partial,
 734          value = holder[key];
 735
 736// If the value has a toJSON method, call it to obtain a replacement value.
 737
 738      if (value instanceof Date) {
 739          value = date(key);
 740      }
 741
 742// If we were called with a replacer function, then call the replacer to
 743// obtain a replacement value.
 744
 745      if (typeof rep === 'function') {
 746          value = rep.call(holder, key, value);
 747      }
 748
 749// What happens next depends on the value's type.
 750
 751      switch (typeof value) {
 752      case 'string':
 753          return quote(value);
 754
 755      case 'number':
 756
 757// JSON numbers must be finite. Encode non-finite numbers as null.
 758
 759          return isFinite(value) ? String(value) : 'null';
 760
 761      case 'boolean':
 762      case 'null':
 763
 764// If the value is a boolean or null, convert it to a string. Note:
 765// typeof null does not produce 'null'. The case is included here in
 766// the remote chance that this gets fixed someday.
 767
 768          return String(value);
 769
 770// If the type is 'object', we might be dealing with an object or an array or
 771// null.
 772
 773      case 'object':
 774
 775// Due to a specification blunder in ECMAScript, typeof null is 'object',
 776// so watch out for that case.
 777
 778          if (!value) {
 779              return 'null';
 780          }
 781
 782// Make an array to hold the partial results of stringifying this object value.
 783
 784          gap += indent;
 785          partial = [];
 786
 787// Is the value an array?
 788
 789          if (Object.prototype.toString.apply(value) === '[object Array]') {
 790
 791// The value is an array. Stringify every element. Use null as a placeholder
 792// for non-JSON values.
 793
 794              length = value.length;
 795              for (i = 0; i < length; i += 1) {
 796                  partial[i] = str(i, value) || 'null';
 797              }
 798
 799// Join all of the elements together, separated with commas, and wrap them in
 800// brackets.
 801
 802              v = partial.length === 0 ? '[]' : gap ?
 803                  '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
 804                  '[' + partial.join(',') + ']';
 805              gap = mind;
 806              return v;
 807          }
 808
 809// If the replacer is an array, use it to select the members to be stringified.
 810
 811          if (rep && typeof rep === 'object') {
 812              length = rep.length;
 813              for (i = 0; i < length; i += 1) {
 814                  if (typeof rep[i] === 'string') {
 815                      k = rep[i];
 816                      v = str(k, value);
 817                      if (v) {
 818                          partial.push(quote(k) + (gap ? ': ' : ':') + v);
 819                      }
 820                  }
 821              }
 822          } else {
 823
 824// Otherwise, iterate through all of the keys in the object.
 825
 826              for (k in value) {
 827                  if (Object.prototype.hasOwnProperty.call(value, k)) {
 828                      v = str(k, value);
 829                      if (v) {
 830                          partial.push(quote(k) + (gap ? ': ' : ':') + v);
 831                      }
 832                  }
 833              }
 834          }
 835
 836// Join all of the member texts together, separated with commas,
 837// and wrap them in braces.
 838
 839          v = partial.length === 0 ? '{}' : gap ?
 840              '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
 841              '{' + partial.join(',') + '}';
 842          gap = mind;
 843          return v;
 844      }
 845  }
 846
 847// If the JSON object does not yet have a stringify method, give it one.
 848
 849  JSON.stringify = function (value, replacer, space) {
 850
 851// The stringify method takes a value and an optional replacer, and an optional
 852// space parameter, and returns a JSON text. The replacer can be a function
 853// that can replace values, or an array of strings that will select the keys.
 854// A default replacer method can be provided. Use of the space parameter can
 855// produce text that is more easily readable.
 856
 857      var i;
 858      gap = '';
 859      indent = '';
 860
 861// If the space parameter is a number, make an indent string containing that
 862// many spaces.
 863
 864      if (typeof space === 'number') {
 865          for (i = 0; i < space; i += 1) {
 866              indent += ' ';
 867          }
 868
 869// If the space parameter is a string, it will be used as the indent string.
 870
 871      } else if (typeof space === 'string') {
 872          indent = space;
 873      }
 874
 875// If there is a replacer, it must be a function or an array.
 876// Otherwise, throw an error.
 877
 878      rep = replacer;
 879      if (replacer && typeof replacer !== 'function' &&
 880              (typeof replacer !== 'object' ||
 881              typeof replacer.length !== 'number')) {
 882          throw new Error('JSON.stringify');
 883      }
 884
 885// Make a fake root object containing our value under the key of ''.
 886// Return the result of stringifying the value.
 887
 888      return str('', {'': value});
 889  };
 890
 891// If the JSON object does not yet have a parse method, give it one.
 892
 893  JSON.parse = function (text, reviver) {
 894  // The parse method takes a text and an optional reviver function, and returns
 895  // a JavaScript value if the text is a valid JSON text.
 896
 897      var j;
 898
 899      function walk(holder, key) {
 900
 901  // The walk method is used to recursively walk the resulting structure so
 902  // that modifications can be made.
 903
 904          var k, v, value = holder[key];
 905          if (value && typeof value === 'object') {
 906              for (k in value) {
 907                  if (Object.prototype.hasOwnProperty.call(value, k)) {
 908                      v = walk(value, k);
 909                      if (v !== undefined) {
 910                          value[k] = v;
 911                      } else {
 912                          delete value[k];
 913                      }
 914                  }
 915              }
 916          }
 917          return reviver.call(holder, key, value);
 918      }
 919
 920
 921  // Parsing happens in four stages. In the first stage, we replace certain
 922  // Unicode characters with escape sequences. JavaScript handles many characters
 923  // incorrectly, either silently deleting them, or treating them as line endings.
 924
 925      text = String(text);
 926      cx.lastIndex = 0;
 927      if (cx.test(text)) {
 928          text = text.replace(cx, function (a) {
 929              return '\\u' +
 930                  ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
 931          });
 932      }
 933
 934  // In the second stage, we run the text against regular expressions that look
 935  // for non-JSON patterns. We are especially concerned with '()' and 'new'
 936  // because they can cause invocation, and '=' because it can cause mutation.
 937  // But just to be safe, we want to reject all unexpected forms.
 938
 939  // We split the second stage into 4 regexp operations in order to work around
 940  // crippling inefficiencies in IE's and Safari's regexp engines. First we
 941  // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
 942  // replace all simple value tokens with ']' characters. Third, we delete all
 943  // open brackets that follow a colon or comma or that begin the text. Finally,
 944  // we look to see that the remaining characters are only whitespace or ']' or
 945  // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
 946
 947      if (/^[\],:{}\s]*$/
 948              .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
 949                  .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
 950                  .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
 951
 952  // In the third stage we use the eval function to compile the text into a
 953  // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
 954  // in JavaScript: it can begin a block or an object literal. We wrap the text
 955  // in parens to eliminate the ambiguity.
 956
 957          j = eval('(' + text + ')');
 958
 959  // In the optional fourth stage, we recursively walk the new structure, passing
 960  // each name/value pair to a reviver function for possible transformation.
 961
 962          return typeof reviver === 'function' ?
 963              walk({'': j}, '') : j;
 964      }
 965
 966  // If the text is not JSON parseable, then a SyntaxError is thrown.
 967
 968      throw new SyntaxError('JSON.parse');
 969  };
 970
 971})(
 972    'undefined' != typeof io ? io : module.exports
 973  , typeof JSON !== 'undefined' ? JSON : undefined
 974);
 975
 976/**
 977 * socket.io
 978 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 979 * MIT Licensed
 980 */
 981
 982(function (exports, io) {
 983
 984  /**
 985   * Parser namespace.
 986   *
 987   * @namespace
 988   */
 989
 990  var parser = exports.parser = {};
 991
 992  /**
 993   * Packet types.
 994   */
 995
 996  var packets = parser.packets = [
 997      'disconnect'
 998    , 'connect'
 999    , 'heartbeat'
1000    , 'message'
1001    , 'json'
1002    , 'event'
1003    , 'ack'
1004    , 'error'
1005    , 'noop'
1006  ];
1007
1008  /**
1009   * Errors reasons.
1010   */
1011
1012  var reasons = parser.reasons = [
1013      'transport not supported'
1014    , 'client not handshaken'
1015    , 'unauthorized'
1016  ];
1017
1018  /**
1019   * Errors advice.
1020   */
1021
1022  var advice = parser.advice = [
1023      'reconnect'
1024  ];
1025
1026  /**
1027   * Shortcuts.
1028   */
1029
1030  var JSON = io.JSON
1031    , indexOf = io.util.indexOf;
1032
1033  /**
1034   * Encodes a packet.
1035   *
1036   * @api private
1037   */
1038
1039  parser.encodePacket = function (packet) {
1040    var type = indexOf(packets, packet.type)
1041      , id = packet.id || ''
1042      , endpoint = packet.endpoint || ''
1043      , ack = packet.ack
1044      , data = null;
1045
1046    switch (packet.type) {
1047      case 'error':
1048        var reason = packet.reason ? indexOf(reasons, packet.reason) : ''
1049          , adv = packet.advice ? indexOf(advice, packet.advice) : '';
1050
1051        if (reason !== '' || adv !== '')
1052          data = reason + (adv !== '' ? ('+' + adv) : '');
1053
1054        break;
1055
1056      case 'message':
1057        if (packet.data !== '')
1058          data = packet.data;
1059        break;
1060
1061      case 'event':
1062        var ev = { name: packet.name };
1063
1064        if (packet.args && packet.args.length) {
1065          ev.args = packet.args;
1066        }
1067
1068        data = JSON.stringify(ev);
1069        break;
1070
1071      case 'json':
1072        data = JSON.stringify(packet.data);
1073        break;
1074
1075      case 'connect':
1076        if (packet.qs)
1077          data = packet.qs;
1078        break;
1079
1080      case 'ack':
1081        data = packet.ackId
1082          + (packet.args && packet.args.length
1083              ? '+' + JSON.stringify(packet.args) : '');
1084        break;
1085    }
1086
1087    // construct packet with required fragments
1088    var encoded = [
1089        type
1090      , id + (ack == 'data' ? '+' : '')
1091      , endpoint
1092    ];
1093
1094    // data fragment is optional
1095    if (data !== null && data !== undefined)
1096      encoded.push(data);
1097
1098    return encoded.join(':');
1099  };
1100
1101  /**
1102   * Encodes multiple messages (payload).
1103   *
1104   * @param {Array} messages
1105   * @api private
1106   */
1107
1108  parser.encodePayload = function (packets) {
1109    var decoded = '';
1110
1111    if (packets.length == 1)
1112      return packets[0];
1113
1114    for (var i = 0, l = packets.length; i < l; i++) {
1115      var packet = packets[i];
1116      decoded += '\ufffd' + packet.length + '\ufffd' + packets[i];
1117    }
1118
1119    return decoded;
1120  };
1121
1122  /**
1123   * Decodes a packet
1124   *
1125   * @api private
1126   */
1127
1128  var regexp = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/;
1129
1130  parser.decodePacket = function (data) {
1131    var pieces = data.match(regexp);
1132
1133    if (!pieces) return {};
1134
1135    var id = pieces[2] || ''
1136      , data = pieces[5] || ''
1137      , packet = {
1138            type: packets[pieces[1]]
1139          , endpoint: pieces[4] || ''
1140        };
1141
1142    // whether we need to acknowledge the packet
1143    if (id) {
1144      packet.id = id;
1145      if (pieces[3])
1146        packet.ack = 'data';
1147      else
1148        packet.ack = true;
1149    }
1150
1151    // handle different packet types
1152    switch (packet.type) {
1153      case 'error':
1154        var pieces = data.split('+');
1155        packet.reason = reasons[pieces[0]] || '';
1156        packet.advice = advice[pieces[1]] || '';
1157        break;
1158
1159      case 'message':
1160        packet.data = data || '';
1161        break;
1162
1163      case 'event':
1164        try {
1165          var opts = JSON.parse(data);
1166          packet.name = opts.name;
1167          packet.args = opts.args;
1168        } catch (e) { }
1169
1170        packet.args = packet.args || [];
1171        break;
1172
1173      case 'json':
1174        try {
1175          packet.data = JSON.parse(data);
1176        } catch (e) { }
1177        break;
1178
1179      case 'connect':
1180        packet.qs = data || '';
1181        break;
1182
1183      case 'ack':
1184        var pieces = data.match(/^([0-9]+)(\+)?(.*)/);
1185        if (pieces) {
1186          packet.ackId = pieces[1];
1187          packet.args = [];
1188
1189          if (pieces[3]) {
1190            try {
1191              packet.args = pieces[3] ? JSON.parse(pieces[3]) : [];
1192            } catch (e) { }
1193          }
1194        }
1195        break;
1196
1197      case 'disconnect':
1198      case 'heartbeat':
1199        break;
1200    };
1201
1202    return packet;
1203  };
1204
1205  /**
1206   * Decodes data payload. Detects multiple messages
1207   *
1208   * @return {Array} messages
1209   * @api public
1210   */
1211
1212  parser.decodePayload = function (data) {
1213    // IE doesn't like data[i] for unicode chars, charAt works fine
1214    if (data.charAt(0) == '\ufffd') {
1215      var ret = [];
1216
1217      for (var i = 1, length = ''; i < data.length; i++) {
1218        if (data.charAt(i) == '\ufffd') {
1219          ret.push(parser.decodePacket(data.substr(i + 1).substr(0, length)));
1220          i += Number(length) + 1;
1221          length = '';
1222        } else {
1223          length += data.charAt(i);
1224        }
1225      }
1226
1227      return ret;
1228    } else {
1229      return [parser.decodePacket(data)];
1230    }
1231  };
1232
1233})(
1234    'undefined' != typeof io ? io : module.exports
1235  , 'undefined' != typeof io ? io : module.parent.exports
1236);
1237/**
1238 * socket.io
1239 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
1240 * MIT Licensed
1241 */
1242
1243(function (exports, io) {
1244
1245  /**
1246   * Expose constructor.
1247   */
1248
1249  exports.Transport = Transport;
1250
1251  /**
1252   * This is the transport template for all supported transport methods.
1253   *
1254   * @constructor
1255   * @api public
1256   */
1257
1258  function Transport (socket, sessid) {
1259    this.socket = socket;
1260    this.sessid = sessid;
1261  };
1262
1263  /**
1264   * Apply EventEmitter mixin.
1265   */
1266
1267  io.util.mixin(Transport, io.EventEmitter);
1268
1269  /**
1270   * Handles the response from the server. When a new response is received
1271   * it will automatically update the timeout, decode the message and
1272   * forwards the response to the onMessage function for further processing.
1273   *
1274   * @param {String} data Response from the server.
1275   * @api private
1276   */
1277
1278  Transport.prototype.onData = function (data) {
1279    this.clearCloseTimeout();
1280    
1281    // If the connection in currently open (or in a reopening state) reset the close 
1282    // timeout since we have just received data. This check is necessary so
1283    // that we don't reset the timeout on an explicitly disconnected connection.
1284    if (this.socket.connected || this.socket.connecting || this.socket.reconnecting) {
1285      this.setCloseTimeout();
1286    }
1287
1288    if (data !== '') {
1289      // todo: we should only do decodePayload for xhr transports
1290      var msgs = io.parser.decodePayload(data);
1291
1292      if (msgs && msgs.length) {
1293        for (var i = 0, l = msgs.length; i < l; i++) {
1294          this.onPacket(msgs[i]);
1295        }
1296      }
1297    }
1298
1299    return this;
1300  };
1301
1302  /**
1303   * Handles packets.
1304   *
1305   * @api private
1306   */
1307
1308  Transport.prototype.onPacket = function (packet) {
1309    this.socket.setHeartbeatTimeout();
1310
1311    if (packet.type == 'heartbeat') {
1312      return this.onHeartbeat();
1313    }
1314
1315    if (packet.type == 'connect' && packet.endpoint == '') {
1316      this.onConnect();
1317    }
1318
1319    if (packet.type == 'error' && packet.advice == 'reconnect') {
1320      this.open = false;
1321    }
1322
1323    this.socket.onPacket(packet);
1324
1325    return this;
1326  };
1327
1328  /**
1329   * Sets close timeout
1330   *
1331   * @api private
1332   */
1333  
1334  Transport.prototype.setCloseTimeout = function () {
1335    if (!this.closeTimeout) {
1336      var self = this;
1337
1338      this.closeTimeout = setTimeout(function () {
1339        self.onDisconnect();
1340      }, this.socket.closeTimeout);
1341    }
1342  };
1343
1344  /**
1345   * Called when transport disconnects.
1346   *
1347   * @api private
1348   */
1349
1350  Transport.prototype.onDisconnect = function () {
1351    if (this.close && this.open) this.close();
1352    this.clearTimeouts();
1353    this.socket.onDisconnect();
1354    return this;
1355  };
1356
1357  /**
1358   * Called when transport connects
1359   *
1360   * @api private
1361   */
1362
1363  Transport.prototype.onConnect = function () {
1364    this.socket.onConnect();
1365    return this;
1366  }
1367
1368  /**
1369   * Clears close timeout
1370   *
1371   * @api private
1372   */
1373
1374  Transport.prototype.clearCloseTimeout = function () {
1375    if (this.closeTimeout) {
1376      clearTimeout(this.closeTimeout);
1377      this.closeTimeout = null;
1378    }
1379  };
1380
1381  /**
1382   * Clear timeouts
1383   *
1384   * @api private
1385   */
1386
1387  Transport.prototype.clearTimeouts = function () {
1388    this.clearCloseTimeout();
1389
1390    if (this.reopenTimeout) {
1391      clearTimeout(this.reopenTimeout);
1392    }
1393  };
1394
1395  /**
1396   * Sends a packet
1397   *
1398   * @param {Object} packet object.
1399   * @api private
1400   */
1401
1402  Transport.prototype.packet = function (packet) {
1403    this.send(io.parser.encodePacket(packet));
1404  };
1405
1406  /**
1407   * Send the received heartbeat message back to server. So the server
1408   * knows we are still connected.
1409   *
1410   * @param {String} heartbeat Heartbeat response from the server.
1411   * @api private
1412   */
1413
1414  Transport.prototype.onHeartbeat = function (heartbeat) {
1415    this.packet({ type: 'heartbeat' });
1416  };
1417 
1418  /**
1419   * Called when the transport opens.
1420   *
1421   * @api private
1422   */
1423
1424  Transport.prototype.onOpen = function () {
1425    this.open = true;
1426    this.clearCloseTimeout();
1427    this.socket.onOpen();
1428  };
1429
1430  /**
1431   * Notifies the base when the connection with the Socket.IO server
1432   * has been disconnected.
1433   *
1434   * @api private
1435   */
1436
1437  Transport.prototype.onClose = function () {
1438    var self = this;
1439
1440    /* FIXME: reopen delay causing a infinit loop
1441    this.reopenTimeout = setTimeout(function () {
1442      self.open();
1443    }, this.socket.options['reopen delay']);*/
1444
1445    this.open = false;
1446    this.socket.onClose();
1447    this.onDisconnect();
1448  };
1449
1450  /**
1451   * Generates a connection url based on the Socket.IO URL Protocol.
1452   * See <https://github.com/learnboost/socket.io-node/> for more details.
1453   *
1454   * @returns {String} Connection url
1455   * @api private
1456   */
1457
1458  Transport.prototype.prepareUrl = function () {
1459    var options = this.socket.options;
1460
1461    return this.scheme() + '://'
1462      + options.host + ':' + options.port + '/'
1463      + options.resource + '/' + io.protocol
1464      + '/' + this.name + '/' + this.sessid;
1465  };
1466
1467  /**
1468   * Checks if the transport is ready to start a connection.
1469   *
1470   * @param {Socket} socket The socket instance that needs a transport
1471   * @param {Function} fn The callback
1472   * @api private
1473   */
1474
1475  Transport.prototype.ready = function (socket, fn) {
1476    fn.call(this);
1477  };
1478})(
1479    'undefined' != typeof io ? io : module.exports
1480  , 'undefined' != typeof io ? io : module.parent.exports
1481);
1482/**
1483 * socket.io
1484 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
1485 * MIT Licensed
1486 */
1487
1488(function (exports, io, global) {
1489
1490  /**
1491   * Expose constructor.
1492   */
1493
1494  exports.Socket = Socket;
1495
1496  /**
1497   * Create a new `Socket.IO client` which can establish a persistent
1498   * connection with a Socket.IO enabled server.
1499   *
1500   * @api public
1501   */
1502
1503  function Socket (options) {
1504    this.options = {
1505        port: 80
1506      , secure: false
1507      , document: 'document' in global ? document : false
1508      , resource: 'socket.io'
1509      , transports: io.transports
1510      , 'connect timeout': 10000
1511      , 'try multiple transports': true
1512      , 'reconnect': true
1513      , 'reconnection delay': 500
1514      , 'reconnection limit': Infinity
1515      , 'reopen delay': 3000
1516      , 'max reconnection attempts': 10
1517      , 'sync disconnect on unload': true
1518      , 'auto connect': true
1519      , 'flash policy port': 10843
1520    };
1521
1522    io.util.merge(this.options, options);
1523
1524    this.connected = false;
1525    this.open = false;
1526    this.connecting = false;
1527    this.reconnecting = false;
1528    this.namespaces = {};
1529    this.buffer = [];
1530    this.doBuffer = false;
1531
1532    if (this.options['sync disconnect on unload'] &&
1533        (!this.isXDomain() || io.util.ua.hasCORS)) {
1534      var self = this;
1535
1536      io.util.on(global, 'unload', function () {
1537        self.disconnectSync();
1538      }, false);
1539    }
1540
1541    if (this.options['auto connect']) {
1542      this.connect();
1543    }
1544};
1545
1546  /**
1547   * Apply EventEmitter mixin.
1548   */
1549
1550  io.util.mixin(Socket, io.EventEmitter);
1551
1552  /**
1553   * Returns a namespace listener/emitter for this socket
1554   *
1555   * @api public
1556   */
1557
1558  Socket.prototype.of = function (name) {
1559    if (!this.namespaces[name]) {
1560      this.namespaces[name] = new io.SocketNamespace(this, name);
1561
1562      if (name !== '') {
1563        this.namespaces[name].packet({ type: 'connect' });
1564      }
1565    }
1566
1567    return this.namespaces[name];
1568  };
1569
1570  /**
1571   * Emits the given event to the Socket and all namespaces
1572   *
1573   * @api private
1574   */
1575
1576  Socket.prototype.publish = function () {
1577    this.emit.apply(this, arguments);
1578
1579    var nsp;
1580
1581    for (var i in this.namespaces) {
1582      if (this.namespaces.hasOwnProperty(i)) {
1583        nsp = this.of(i);
1584        nsp.$emit.apply(nsp, arguments);
1585      }
1586    }
1587  };
1588
1589  /**
1590   * Performs the handshake
1591   *
1592   * @api private
1593   */
1594
1595  function empty () { };
1596
1597  Socket.prototype.handshake = function (fn) {
1598    var self = this
1599      , options = this.options;
1600
1601    function complete (data) {
1602      if (data instanceof Error) {
1603        self.connecting = false;
1604        self.onError(data.message);
1605      } else {
1606        fn.apply(null, data.split(':'));
1607      }
1608    };
1609
1610    var url = [
1611          'http' + (options.secure ? 's' : '') + ':/'
1612        , options.host + ':' + options.port
1613        , options.resource
1614        , io.protocol
1615        , io.util.query(this.options.query, 't=' + +new Date)
1616      ].join('/');
1617
1618    if (this.isXDomain() && !io.util.ua.hasCORS) {
1619      var insertAt = document.getElementsByTagName('script')[0]
1620        , script = document.createElement('script');
1621
1622      script.src = url + '&jsonp=' + io.j.length;
1623      insertAt.parentNode.insertBefore(script, insertAt);
1624
1625      io.j.push(function (data) {
1626        complete(data);
1627        script.parentNode.removeChild(script);
1628      });
1629    } else {
1630      var xhr = io.util.request();
1631
1632      xhr.open('GET', url, true);
1633      xhr.withCredentials = true;
1634      xhr.onreadystatechange = function () {
1635        if (xhr.readyState == 4) {
1636          xhr.onreadystatechange = empty;
1637
1638          if (xhr.status == 200) {
1639            complete(xhr.responseText);
1640          } else {
1641            self.connecting = false;            
1642            !self.reconnecting && self.onError(xhr.responseText);
1643          }
1644        }
1645      };
1646      xhr.send(null);
1647    }
1648  };
1649
1650  /**
1651   * Find an available transport based on the options supplied in the constructor.
1652   *
1653   * @api private
1654   */
1655
1656  Socket.prototype.getTransport = function (override) {
1657    var transports = override || this.transports, match;
1658
1659    for (var i = 0, transport; transport = transports[i]; i++) {
1660      if (io.Transport[transport]
1661        && io.Transport[transport].check(this)
1662        && (!this.isXDomain() || io.Transport[transport].xdomainCheck())) {
1663        return new io.Transport[transport](this, this.sessionid);
1664      }
1665    }
1666
1667    return null;
1668  };
1669
1670  /**
1671   * Connects to the server.
1672   *
1673   * @param {Function} [fn] Callback.
1674   * @returns {io.Socket}
1675   * @api public
1676   */
1677
1678  Socket.prototype.connect = function (fn) {
1679    if (this.connecting) {
1680      return this;
1681    }
1682
1683    var self = this;
1684    self.connecting = true;
1685    
1686    this.handshake(function (sid, heartbeat, close, transports) {
1687      self.sessionid = sid;
1688      self.closeTimeout = close * 1000;
1689      self.heartbeatTimeout = heartbeat * 1000;
1690      self.transports = transports ? io.util.intersect(
1691          transports.split(',')
1692        , self.options.transports
1693      ) : self.options.transports;
1694
1695      self.setHeartbeatTimeout();
1696
1697      function connect (transports){
1698        if (self.transport) self.transport.clearTimeouts();
1699
1700        self.transport = self.getTransport(transports);
1701        if (!self.transport) return self.publish('connect_failed');
1702
1703        // once the transport is ready
1704        self.transport.ready(self, function () {
1705          self.connecting = true;
1706          self.publish('connecting', self.transport.name);
1707          self.transport.open();
1708
1709          if (self.options['connect timeout']) {
1710            self.connectTimeoutTimer = setTimeout(function () {
1711              if (!self.connected) {
1712                self.connecting = false;
1713
1714                if (self.options['try multiple transports']) {
1715                  if (!self.remainingTransports) {
1716                    self.remainingTransports = self.transports.slice(0);
1717                  }
1718
1719                  var remaining = self.remainingTransports;
1720
1721                  while (remaining.length > 0 && remaining.splice(0,1)[0] !=
1722                         self.transport.name) {}
1723
1724                    if (remaining.length){
1725                      connect(remaining);
1726                    } else {
1727                      self.publish('connect_failed');
1728                    }
1729                }
1730              }
1731            }, self.options['connect timeout']);
1732          }
1733        });
1734      }
1735
1736      connect(self.transports);
1737
1738      self.once('connect', function (){
1739        clearTimeout(self.connectTimeoutTimer);
1740
1741        fn && typeof fn == 'function' && fn();
1742      });
1743    });
1744
1745    return this;
1746  };
1747
1748  /**
1749   * Clears and sets a new heartbeat timeout using the value given by the
1750   * server during the handshake.
1751   *
1752   * @api private
1753   */
1754
1755  Socket.prototype.setHeartbeatTimeout = function () {
1756    clearTimeout(this.heartbeatTimeoutTimer);
1757
1758    var self = this;
1759    this.heartbeatTimeoutTimer = setTimeout(function () {
1760      self.transport.onClose();
1761    }, this.heartbeatTimeout);
1762  };
1763
1764  /**
1765   * Sends a message.
1766   *
1767   * @param {Object} data packet.
1768   * @returns {io.Socket}
1769   * @api public
1770   */
1771
1772  Socket.prototype.packet = function (data) {
1773    if (this.connected && !this.doBuffer) {
1774      this.transport.packet(data);
1775    } else {
1776      this.buffer.push(data);
1777    }
1778
1779    return this;
1780  };
1781
1782  /**
1783   * Sets buffer state
1784   *
1785   * @api private
1786   */
1787
1788  Socket.prototype.setBuffer = function (v) {
1789    this.doBuffer = v;
1790
1791    if (!v && this.connected && this.buffer.length) {
1792      this.transport.payload(this.buffer);
1793      this.buffer = [];
1794    }
1795  };
1796
1797  /**
1798   * Disconnect the established connect.
1799   *
1800   * @returns {io.Socket}
1801   * @api public
1802   */
1803
1804  Socket.prototype.disconnect = function () {
1805    if (this.connected || this.connecting) {
1806      if (this.open) {
1807        this.of('').packet({ type: 'disconnect' });
1808      }
1809
1810      // handle disconnection immediately
1811      this.onDisconnect('booted');
1812    }
1813
1814    return this;
1815  };
1816
1817  /**
1818   * Disconnects the socket with a sync XHR.
1819   *
1820   * @api private
1821   */
1822
1823  Socket.prototype.disconnectSync = function () {
1824    // ensure disconnection
1825    var xhr = io.util.request()
1826      , uri = this.resource + '/' + io.protocol + '/' + this.sessionid;
1827
1828    xhr.open('GET', uri, true);
1829
1830    // handle disconnection immediately
1831    this.onDisconnect('booted');
1832  };
1833
1834  /**
1835   * Check if we need to use cross domain enabled transports. Cross domain would
1836   * be a different port or different domain name.
1837   *
1838   * @returns {Boolean}
1839   * @api private
1840   */
1841
1842  Socket.prototype.isXDomain = function () {
1843
1844    var port = global.location.port ||
1845      ('https:' == global.location.protocol ? 443 : 80);
1846
1847    return this.options.host !== global.location.hostname 
1848      || this.options.port != port;
1849  };
1850
1851  /**
1852   * Called upon handshake.
1853   *
1854   * @api private
1855   */
1856
1857  Socket.prototype.onConnect = function () {
1858    if (!this.connected) {
1859      this.connected = true;
1860      this.connecting = false;
1861      if (!this.doBuffer) {
1862        // make sure to flush the buffer
1863        this.setBuffer(false);
1864      }
1865      this.emit('connect');
1866    }
1867  };
1868
1869  /**
1870   * Called when the transport opens
1871   *
1872   * @api private
1873   */
1874
1875  Socket.prototype.onOpen = function () {
1876    this.open = true;
1877  };
1878
1879  /**
1880   * Called when the transport closes.
1881   *
1882   * @api private
1883   */
1884
1885  Socket.prototype.onClose = function () {
1886    this.open = false;
1887    clearTimeout(this.heartbeatTimeoutTimer);
1888  };
1889
1890  /**
1891   * Called when the transport first opens a connection
1892   *
1893   * @param text
1894   */
1895
1896  Socket.prototype.onPacket = function (packet) {
1897    this.of(packet.endpoint).onPacket(packet);
1898  };
1899
1900  /**
1901   * Handles an error.
1902   *
1903   * @api private
1904   */
1905
1906  Socket.prototype.onError = function (err) {
1907    if (err && err.advice) {
1908      if (err.advice === 'reconnect' && (this.connected || this.connecting)) {
1909        this.disconnect();
1910        if (this.options.reconnect) {
1911          this.reconnect();
1912        }
1913      }
1914    }
1915
1916    this.publish('error', err && err.reason ? err.reason : err);
1917  };
1918
1919  /**
1920   * Called when the transport disconnects.
1921   *
1922   * @api private
1923   */
1924
1925  Socket.prototype.onDisconnect = function (reason) {
1926    var wasConnected = this.connected
1927      , wasConnecting = this.connecting;
1928
1929    this.connected = false;
1930    this.connecting = false;
1931    this.open = false;
1932
1933    if (wasConnected || wasConnecting) {
1934      this.transport.close();
1935      this.transport.clearTimeouts();
1936      if (wasConnected) {
1937        this.publish('disconnect', reason);
1938
1939        if ('booted' != reason && this.options.reconnect && !this.reconnecting) {
1940          this.reconnect();
1941        }
1942      }
1943    }
1944  };
1945
1946  /**
1947   * Called upon reconnection.
1948   *
1949   * @api private
1950   */
1951
1952  Socket.prototype.reconnect = function () {
1953    this.reconnecting = true;
1954    this.reconnectionAttempts = 0;
1955    this.reconnectionDelay = this.options['reconnection delay'];
1956
1957    var self = this
1958      , maxAttempts = this.options['max reconnection attempts']
1959      , tryMultiple = this.options['try multiple transports']
1960      , limit = this.options['reconnection limit'];
1961
1962    function reset () {
1963      if (self.connected) {
1964        for (var i in self.namespaces) {
1965          if (self.namespaces.hasOwnProperty(i) && '' !== i) {
1966              self.namespaces[i].packet({ type: 'connect' });
1967          }
1968        }
1969        self.publish('reconnect', self.transport.name, self.reconnectionAttempts);
1970      }
1971
1972      clearTimeout(self.reconnectionTimer);
1973
1974      self.removeListener('connect_failed', maybeReconnect);
1975      self.removeListener('connect', maybeReconnect);
1976
1977      self.reconnecting = false;
1978
1979      delete self.reconnectionAttempts;
1980      delete self.reconnectionDelay;
1981      delete self.reconnectionTimer;
1982      delete self.redoTransports;
1983
1984      self.options['try multiple transports'] = tryMultiple;
1985    };
1986
1987    function maybeReconnect () {
1988      if (!self.reconnecting) {
1989        return;
1990      }
1991
1992      if (self.connected) {
1993        return reset();
1994      };
1995
1996      if (self.connecting && self.reconnecting) {
1997        return self.reconnectionTimer = setTimeout(maybeReconnect, 1000);
1998      }
1999
2000      if (self.reconnectionAttempts++ >= maxAttempts) {
2001        if (!self.redoTransports) {
2002          self.on('connect_failed', maybeReconnect);
2003          self.options['try multiple transports'] = true;
2004          self.transport = self.getTransport();
2005          self.redoTransports = true;
2006          self.connect();
2007        } else {
2008          self.publish('reconnect_failed');
2009          reset();
2010        }
2011      } else {
2012        if (self.reconnectionDelay < limit) {
2013          self.reconnectionDelay *= 2; // exponential back off
2014        }
2015
2016        self.connect();
2017        self.publish('reconnecting', self.reconnectionDelay, self.reconnectionAttempts);
2018        self.reconnectionTimer = setTimeout(maybeReconnect, self.reconnectionDelay);
2019      }
2020    };
2021
2022    this.options['try multiple transports'] = false;
2023    this.reconnectionTimer = setTimeout(maybeReconnect, this.reconnectionDelay);
2024
2025    this.on('connect', maybeReconnect);
2026  };
2027
2028})(
2029    'undefined' != typeof io ? io : module.exports
2030  , 'undefined' != typeof io ? io : module.parent.exports
2031  , this
2032);
2033/**
2034 * socket.io
2035 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
2036 * MIT Licensed
2037 */
2038
2039(function (exports, io) {
2040
2041  /**
2042   * Expose constructor.
2043   */
2044
2045  exports.SocketNamespace = SocketNamespace;
2046
2047  /**
2048   * Socket namespace constructor.
2049   *
2050   * @constructor
2051   * @api public
2052   */
2053
2054  function SocketNamespace (socket, name) {
2055    this.socket = socket;
2056    this.name = name || '';
2057    this.flags = {};
2058    this.json = new Flag(this, 'json');
2059    this.ackPackets = 0;
2060    this.acks = {};
2061  };
2062
2063  /**
2064   * Apply EventEmitter mixin.
2065   */
2066
2067  io.util.mixin(SocketNamespace, io.EventEmitter);
2068
2069  /**
2070   * Copies emit since we override it
2071   *
2072   * @api private
2073   */
2074
2075  SocketNamespace.prototype.$emit = io.EventEmitter.prototype.emit;
2076
2077  /**
2078   * Creates a new namespace, by proxying the request to the socket. This
2079   * allows us to use the synax as we do on the server.
2080   *
2081   * @api public
2082   */
2083
2084  SocketNamespace.prototype.of = function () {
2085    return this.socket.of.apply(this.socket, arguments);
2086  };
2087
2088  /**
2089   * Sends a packet.
2090   *
2091   * @api private
2092   */
2093
2094  SocketNamespace.prototype.packet = function (packet) {
2095    packet.endpoint = this.name;
2096    this.socket.packet(packet);
2097    this.flags = {};
2098    return this;
2099  };
2100
2101  /**
2102   * Sends a message
2103   *
2104   * @api public
2105   */
2106
2107  SocketNamespace.prototype.send = function (data, fn) {
2108    var packet = {
2109        type: this.flags.json ? 'json' : 'message'
2110      , data: data
2111    };
2112
2113    if ('function' == typeof fn) {
2114      packet.id = ++this.ackPackets;
2115      packet.ack = true;
2116      this.acks[packet.id] = fn;
2117    }
2118
2119    return this.packet(packet);
2120  };
2121
2122  /**
2123   * Emits an event
2124   *
2125   * @api public
2126   */
2127  
2128  SocketNamespace.prototype.emit = function (name) {
2129    var args = Array.prototype.slice.call(arguments, 1)
2130      , lastArg = args[args.length - 1]
2131      , packet = {
2132            type: 'event'
2133          , name: name
2134        };
2135
2136    if ('function' == typeof lastArg) {
2137      packet.id = ++this.ackPackets;
2138      packet.ack = 'data';
2139      this.acks[packet.id] = lastArg;
2140      args = args.slice(0, args.length - 1);
2141    }
2142
2143    packet.args = args;
2144
2145    return this.packet(packet);
2146  };
2147
2148  /**
2149   * Disconnects the namespace
2150   *
2151   * @api private
2152   */
2153
2154  SocketNamespace.prototype.disconnect = function () {
2155    if (this.name === '') {
2156      this.socket.disconnect();
2157    } else {
2158      this.packet({ type: 'disconnect' });
2159      this.$emit('disconnect');
2160    }
2161
2162    return this;
2163  };
2164
2165  /**
2166   * Handles a packet
2167   *
2168   * @api private
2169   */
2170
2171  SocketNamespace.prototype.onPacket = function (packet) {
2172    var self = this;
2173
2174    function ack () {
2175      self.packet({
2176          type: 'ack'
2177        , args: io.util.toArray(arguments)
2178        , ackId: packet.id
2179      });
2180    };
2181
2182    switch (packet.type) {
2183      case 'connect':
2184        this.$emit('connect');
2185        break;
2186
2187      case 'disconnect':
2188        if (this.name === '') {
2189          this.socket.onDisconnect(packet.reason || 'booted');
2190        } else {
2191          this.$emit('disconnect', packet.reason);
2192        }
2193        break;
2194
2195      case 'message':
2196      case 'json':
2197        var params = ['message', packet.data];
2198
2199      

Large files files are truncated, but you can click here to view the full file