PageRenderTime 67ms CodeModel.GetById 4ms app.highlight 49ms RepoModel.GetById 1ms app.codeStats 0ms

/public/vendors/socket.io.js

https://github.com/victorferreira/tv.js
JavaScript | 3327 lines | 2953 code | 147 blank | 227 comment | 113 complexity | dfcd0f8a4ea58a14c1bc5bad5b22cf04 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.16, 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.16';
  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 && !util.ua.hasCORS) {
 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 * socket.io
 471 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 472 * MIT Licensed
 473 */
 474
 475(function (exports, io) {
 476
 477  /**
 478   * Expose constructor.
 479   */
 480
 481  exports.EventEmitter = EventEmitter;
 482
 483  /**
 484   * Event emitter constructor.
 485   *
 486   * @api public.
 487   */
 488
 489  function EventEmitter () {};
 490
 491  /**
 492   * Adds a listener
 493   *
 494   * @api public
 495   */
 496
 497  EventEmitter.prototype.on = function (name, fn) {
 498    if (!this.$events) {
 499      this.$events = {};
 500    }
 501
 502    if (!this.$events[name]) {
 503      this.$events[name] = fn;
 504    } else if (io.util.isArray(this.$events[name])) {
 505      this.$events[name].push(fn);
 506    } else {
 507      this.$events[name] = [this.$events[name], fn];
 508    }
 509
 510    return this;
 511  };
 512
 513  EventEmitter.prototype.addListener = EventEmitter.prototype.on;
 514
 515  /**
 516   * Adds a volatile listener.
 517   *
 518   * @api public
 519   */
 520
 521  EventEmitter.prototype.once = function (name, fn) {
 522    var self = this;
 523
 524    function on () {
 525      self.removeListener(name, on);
 526      fn.apply(this, arguments);
 527    };
 528
 529    on.listener = fn;
 530    this.on(name, on);
 531
 532    return this;
 533  };
 534
 535  /**
 536   * Removes a listener.
 537   *
 538   * @api public
 539   */
 540
 541  EventEmitter.prototype.removeListener = function (name, fn) {
 542    if (this.$events && this.$events[name]) {
 543      var list = this.$events[name];
 544
 545      if (io.util.isArray(list)) {
 546        var pos = -1;
 547
 548        for (var i = 0, l = list.length; i < l; i++) {
 549          if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
 550            pos = i;
 551            break;
 552          }
 553        }
 554
 555        if (pos < 0) {
 556          return this;
 557        }
 558
 559        list.splice(pos, 1);
 560
 561        if (!list.length) {
 562          delete this.$events[name];
 563        }
 564      } else if (list === fn || (list.listener && list.listener === fn)) {
 565        delete this.$events[name];
 566      }
 567    }
 568
 569    return this;
 570  };
 571
 572  /**
 573   * Removes all listeners for an event.
 574   *
 575   * @api public
 576   */
 577
 578  EventEmitter.prototype.removeAllListeners = function (name) {
 579    if (name === undefined) {
 580      this.$events = {};
 581      return this;
 582    }
 583
 584    if (this.$events && this.$events[name]) {
 585      this.$events[name] = null;
 586    }
 587
 588    return this;
 589  };
 590
 591  /**
 592   * Gets all listeners for a certain event.
 593   *
 594   * @api publci
 595   */
 596
 597  EventEmitter.prototype.listeners = function (name) {
 598    if (!this.$events) {
 599      this.$events = {};
 600    }
 601
 602    if (!this.$events[name]) {
 603      this.$events[name] = [];
 604    }
 605
 606    if (!io.util.isArray(this.$events[name])) {
 607      this.$events[name] = [this.$events[name]];
 608    }
 609
 610    return this.$events[name];
 611  };
 612
 613  /**
 614   * Emits an event.
 615   *
 616   * @api public
 617   */
 618
 619  EventEmitter.prototype.emit = function (name) {
 620    if (!this.$events) {
 621      return false;
 622    }
 623
 624    var handler = this.$events[name];
 625
 626    if (!handler) {
 627      return false;
 628    }
 629
 630    var args = Array.prototype.slice.call(arguments, 1);
 631
 632    if ('function' == typeof handler) {
 633      handler.apply(this, args);
 634    } else if (io.util.isArray(handler)) {
 635      var listeners = handler.slice();
 636
 637      for (var i = 0, l = listeners.length; i < l; i++) {
 638        listeners[i].apply(this, args);
 639      }
 640    } else {
 641      return false;
 642    }
 643
 644    return true;
 645  };
 646
 647})(
 648    'undefined' != typeof io ? io : module.exports
 649  , 'undefined' != typeof io ? io : module.parent.exports
 650);
 651
 652/**
 653 * socket.io
 654 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 655 * MIT Licensed
 656 */
 657
 658/**
 659 * Based on JSON2 (http://www.JSON.org/js.html).
 660 */
 661
 662(function (exports, nativeJSON) {
 663  "use strict";
 664
 665  // use native JSON if it's available
 666  if (nativeJSON && nativeJSON.parse){
 667    return exports.JSON = {
 668      parse: nativeJSON.parse
 669    , stringify: nativeJSON.stringify
 670    };
 671  }
 672
 673  var JSON = exports.JSON = {};
 674
 675  function f(n) {
 676      // Format integers to have at least two digits.
 677      return n < 10 ? '0' + n : n;
 678  }
 679
 680  function date(d, key) {
 681    return isFinite(d.valueOf()) ?
 682        d.getUTCFullYear()     + '-' +
 683        f(d.getUTCMonth() + 1) + '-' +
 684        f(d.getUTCDate())      + 'T' +
 685        f(d.getUTCHours())     + ':' +
 686        f(d.getUTCMinutes())   + ':' +
 687        f(d.getUTCSeconds())   + 'Z' : null;
 688  };
 689
 690  var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
 691      escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
 692      gap,
 693      indent,
 694      meta = {    // table of character substitutions
 695          '\b': '\\b',
 696          '\t': '\\t',
 697          '\n': '\\n',
 698          '\f': '\\f',
 699          '\r': '\\r',
 700          '"' : '\\"',
 701          '\\': '\\\\'
 702      },
 703      rep;
 704
 705
 706  function quote(string) {
 707
 708// If the string contains no control characters, no quote characters, and no
 709// backslash characters, then we can safely slap some quotes around it.
 710// Otherwise we must also replace the offending characters with safe escape
 711// sequences.
 712
 713      escapable.lastIndex = 0;
 714      return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
 715          var c = meta[a];
 716          return typeof c === 'string' ? c :
 717              '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
 718      }) + '"' : '"' + string + '"';
 719  }
 720
 721
 722  function str(key, holder) {
 723
 724// Produce a string from holder[key].
 725
 726      var i,          // The loop counter.
 727          k,          // The member key.
 728          v,          // The member value.
 729          length,
 730          mind = gap,
 731          partial,
 732          value = holder[key];
 733
 734// If the value has a toJSON method, call it to obtain a replacement value.
 735
 736      if (value instanceof Date) {
 737          value = date(key);
 738      }
 739
 740// If we were called with a replacer function, then call the replacer to
 741// obtain a replacement value.
 742
 743      if (typeof rep === 'function') {
 744          value = rep.call(holder, key, value);
 745      }
 746
 747// What happens next depends on the value's type.
 748
 749      switch (typeof value) {
 750      case 'string':
 751          return quote(value);
 752
 753      case 'number':
 754
 755// JSON numbers must be finite. Encode non-finite numbers as null.
 756
 757          return isFinite(value) ? String(value) : 'null';
 758
 759      case 'boolean':
 760      case 'null':
 761
 762// If the value is a boolean or null, convert it to a string. Note:
 763// typeof null does not produce 'null'. The case is included here in
 764// the remote chance that this gets fixed someday.
 765
 766          return String(value);
 767
 768// If the type is 'object', we might be dealing with an object or an array or
 769// null.
 770
 771      case 'object':
 772
 773// Due to a specification blunder in ECMAScript, typeof null is 'object',
 774// so watch out for that case.
 775
 776          if (!value) {
 777              return 'null';
 778          }
 779
 780// Make an array to hold the partial results of stringifying this object value.
 781
 782          gap += indent;
 783          partial = [];
 784
 785// Is the value an array?
 786
 787          if (Object.prototype.toString.apply(value) === '[object Array]') {
 788
 789// The value is an array. Stringify every element. Use null as a placeholder
 790// for non-JSON values.
 791
 792              length = value.length;
 793              for (i = 0; i < length; i += 1) {
 794                  partial[i] = str(i, value) || 'null';
 795              }
 796
 797// Join all of the elements together, separated with commas, and wrap them in
 798// brackets.
 799
 800              v = partial.length === 0 ? '[]' : gap ?
 801                  '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
 802                  '[' + partial.join(',') + ']';
 803              gap = mind;
 804              return v;
 805          }
 806
 807// If the replacer is an array, use it to select the members to be stringified.
 808
 809          if (rep && typeof rep === 'object') {
 810              length = rep.length;
 811              for (i = 0; i < length; i += 1) {
 812                  if (typeof rep[i] === 'string') {
 813                      k = rep[i];
 814                      v = str(k, value);
 815                      if (v) {
 816                          partial.push(quote(k) + (gap ? ': ' : ':') + v);
 817                      }
 818                  }
 819              }
 820          } else {
 821
 822// Otherwise, iterate through all of the keys in the object.
 823
 824              for (k in value) {
 825                  if (Object.prototype.hasOwnProperty.call(value, k)) {
 826                      v = str(k, value);
 827                      if (v) {
 828                          partial.push(quote(k) + (gap ? ': ' : ':') + v);
 829                      }
 830                  }
 831              }
 832          }
 833
 834// Join all of the member texts together, separated with commas,
 835// and wrap them in braces.
 836
 837          v = partial.length === 0 ? '{}' : gap ?
 838              '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
 839              '{' + partial.join(',') + '}';
 840          gap = mind;
 841          return v;
 842      }
 843  }
 844
 845// If the JSON object does not yet have a stringify method, give it one.
 846
 847  JSON.stringify = function (value, replacer, space) {
 848
 849// The stringify method takes a value and an optional replacer, and an optional
 850// space parameter, and returns a JSON text. The replacer can be a function
 851// that can replace values, or an array of strings that will select the keys.
 852// A default replacer method can be provided. Use of the space parameter can
 853// produce text that is more easily readable.
 854
 855      var i;
 856      gap = '';
 857      indent = '';
 858
 859// If the space parameter is a number, make an indent string containing that
 860// many spaces.
 861
 862      if (typeof space === 'number') {
 863          for (i = 0; i < space; i += 1) {
 864              indent += ' ';
 865          }
 866
 867// If the space parameter is a string, it will be used as the indent string.
 868
 869      } else if (typeof space === 'string') {
 870          indent = space;
 871      }
 872
 873// If there is a replacer, it must be a function or an array.
 874// Otherwise, throw an error.
 875
 876      rep = replacer;
 877      if (replacer && typeof replacer !== 'function' &&
 878              (typeof replacer !== 'object' ||
 879              typeof replacer.length !== 'number')) {
 880          throw new Error('JSON.stringify');
 881      }
 882
 883// Make a fake root object containing our value under the key of ''.
 884// Return the result of stringifying the value.
 885
 886      return str('', {'': value});
 887  };
 888
 889// If the JSON object does not yet have a parse method, give it one.
 890
 891  JSON.parse = function (text, reviver) {
 892  // The parse method takes a text and an optional reviver function, and returns
 893  // a JavaScript value if the text is a valid JSON text.
 894
 895      var j;
 896
 897      function walk(holder, key) {
 898
 899  // The walk method is used to recursively walk the resulting structure so
 900  // that modifications can be made.
 901
 902          var k, v, value = holder[key];
 903          if (value && typeof value === 'object') {
 904              for (k in value) {
 905                  if (Object.prototype.hasOwnProperty.call(value, k)) {
 906                      v = walk(value, k);
 907                      if (v !== undefined) {
 908                          value[k] = v;
 909                      } else {
 910                          delete value[k];
 911                      }
 912                  }
 913              }
 914          }
 915          return reviver.call(holder, key, value);
 916      }
 917
 918
 919  // Parsing happens in four stages. In the first stage, we replace certain
 920  // Unicode characters with escape sequences. JavaScript handles many characters
 921  // incorrectly, either silently deleting them, or treating them as line endings.
 922
 923      text = String(text);
 924      cx.lastIndex = 0;
 925      if (cx.test(text)) {
 926          text = text.replace(cx, function (a) {
 927              return '\\u' +
 928                  ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
 929          });
 930      }
 931
 932  // In the second stage, we run the text against regular expressions that look
 933  // for non-JSON patterns. We are especially concerned with '()' and 'new'
 934  // because they can cause invocation, and '=' because it can cause mutation.
 935  // But just to be safe, we want to reject all unexpected forms.
 936
 937  // We split the second stage into 4 regexp operations in order to work around
 938  // crippling inefficiencies in IE's and Safari's regexp engines. First we
 939  // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
 940  // replace all simple value tokens with ']' characters. Third, we delete all
 941  // open brackets that follow a colon or comma or that begin the text. Finally,
 942  // we look to see that the remaining characters are only whitespace or ']' or
 943  // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
 944
 945      if (/^[\],:{}\s]*$/
 946              .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
 947                  .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
 948                  .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
 949
 950  // In the third stage we use the eval function to compile the text into a
 951  // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
 952  // in JavaScript: it can begin a block or an object literal. We wrap the text
 953  // in parens to eliminate the ambiguity.
 954
 955          j = eval('(' + text + ')');
 956
 957  // In the optional fourth stage, we recursively walk the new structure, passing
 958  // each name/value pair to a reviver function for possible transformation.
 959
 960          return typeof reviver === 'function' ?
 961              walk({'': j}, '') : j;
 962      }
 963
 964  // If the text is not JSON parseable, then a SyntaxError is thrown.
 965
 966      throw new SyntaxError('JSON.parse');
 967  };
 968
 969})(
 970    'undefined' != typeof io ? io : module.exports
 971  , typeof JSON !== 'undefined' ? JSON : undefined
 972);
 973
 974/**
 975 * socket.io
 976 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 977 * MIT Licensed
 978 */
 979
 980(function (exports, io) {
 981
 982  /**
 983   * Parser namespace.
 984   *
 985   * @namespace
 986   */
 987
 988  var parser = exports.parser = {};
 989
 990  /**
 991   * Packet types.
 992   */
 993
 994  var packets = parser.packets = [
 995      'disconnect'
 996    , 'connect'
 997    , 'heartbeat'
 998    , 'message'
 999    , 'json'
1000    , 'event'
1001    , 'ack'
1002    , 'error'
1003    , 'noop'
1004  ];
1005
1006  /**
1007   * Errors reasons.
1008   */
1009
1010  var reasons = parser.reasons = [
1011      'transport not supported'
1012    , 'client not handshaken'
1013    , 'unauthorized'
1014  ];
1015
1016  /**
1017   * Errors advice.
1018   */
1019
1020  var advice = parser.advice = [
1021      'reconnect'
1022  ];
1023
1024  /**
1025   * Shortcuts.
1026   */
1027
1028  var JSON = io.JSON
1029    , indexOf = io.util.indexOf;
1030
1031  /**
1032   * Encodes a packet.
1033   *
1034   * @api private
1035   */
1036
1037  parser.encodePacket = function (packet) {
1038    var type = indexOf(packets, packet.type)
1039      , id = packet.id || ''
1040      , endpoint = packet.endpoint || ''
1041      , ack = packet.ack
1042      , data = null;
1043
1044    switch (packet.type) {
1045      case 'error':
1046        var reason = packet.reason ? indexOf(reasons, packet.reason) : ''
1047          , adv = packet.advice ? indexOf(advice, packet.advice) : '';
1048
1049        if (reason !== '' || adv !== '')
1050          data = reason + (adv !== '' ? ('+' + adv) : '');
1051
1052        break;
1053
1054      case 'message':
1055        if (packet.data !== '')
1056          data = packet.data;
1057        break;
1058
1059      case 'event':
1060        var ev = { name: packet.name };
1061
1062        if (packet.args && packet.args.length) {
1063          ev.args = packet.args;
1064        }
1065
1066        data = JSON.stringify(ev);
1067        break;
1068
1069      case 'json':
1070        data = JSON.stringify(packet.data);
1071        break;
1072
1073      case 'connect':
1074        if (packet.qs)
1075          data = packet.qs;
1076        break;
1077
1078      case 'ack':
1079        data = packet.ackId
1080          + (packet.args && packet.args.length
1081              ? '+' + JSON.stringify(packet.args) : '');
1082        break;
1083    }
1084
1085    // construct packet with required fragments
1086    var encoded = [
1087        type
1088      , id + (ack == 'data' ? '+' : '')
1089      , endpoint
1090    ];
1091
1092    // data fragment is optional
1093    if (data !== null && data !== undefined)
1094      encoded.push(data);
1095
1096    return encoded.join(':');
1097  };
1098
1099  /**
1100   * Encodes multiple messages (payload).
1101   *
1102   * @param {Array} messages
1103   * @api private
1104   */
1105
1106  parser.encodePayload = function (packets) {
1107    var decoded = '';
1108
1109    if (packets.length == 1)
1110      return packets[0];
1111
1112    for (var i = 0, l = packets.length; i < l; i++) {
1113      var packet = packets[i];
1114      decoded += '\ufffd' + packet.length + '\ufffd' + packets[i];
1115    }
1116
1117    return decoded;
1118  };
1119
1120  /**
1121   * Decodes a packet
1122   *
1123   * @api private
1124   */
1125
1126  var regexp = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/;
1127
1128  parser.decodePacket = function (data) {
1129    var pieces = data.match(regexp);
1130
1131    if (!pieces) return {};
1132
1133    var id = pieces[2] || ''
1134      , data = pieces[5] || ''
1135      , packet = {
1136            type: packets[pieces[1]]
1137          , endpoint: pieces[4] || ''
1138        };
1139
1140    // whether we need to acknowledge the packet
1141    if (id) {
1142      packet.id = id;
1143      if (pieces[3])
1144        packet.ack = 'data';
1145      else
1146        packet.ack = true;
1147    }
1148
1149    // handle different packet types
1150    switch (packet.type) {
1151      case 'error':
1152        var pieces = data.split('+');
1153        packet.reason = reasons[pieces[0]] || '';
1154        packet.advice = advice[pieces[1]] || '';
1155        break;
1156
1157      case 'message':
1158        packet.data = data || '';
1159        break;
1160
1161      case 'event':
1162        try {
1163          var opts = JSON.parse(data);
1164          packet.name = opts.name;
1165          packet.args = opts.args;
1166        } catch (e) { }
1167
1168        packet.args = packet.args || [];
1169        break;
1170
1171      case 'json':
1172        try {
1173          packet.data = JSON.parse(data);
1174        } catch (e) { }
1175        break;
1176
1177      case 'connect':
1178        packet.qs = data || '';
1179        break;
1180
1181      case 'ack':
1182        var pieces = data.match(/^([0-9]+)(\+)?(.*)/);
1183        if (pieces) {
1184          packet.ackId = pieces[1];
1185          packet.args = [];
1186
1187          if (pieces[3]) {
1188            try {
1189              packet.args = pieces[3] ? JSON.parse(pieces[3]) : [];
1190            } catch (e) { }
1191          }
1192        }
1193        break;
1194
1195      case 'disconnect':
1196      case 'heartbeat':
1197        break;
1198    };
1199
1200    return packet;
1201  };
1202
1203  /**
1204   * Decodes data payload. Detects multiple messages
1205   *
1206   * @return {Array} messages
1207   * @api public
1208   */
1209
1210  parser.decodePayload = function (data) {
1211    // IE doesn't like data[i] for unicode chars, charAt works fine
1212    if (data.charAt(0) == '\ufffd') {
1213      var ret = [];
1214
1215      for (var i = 1, length = ''; i < data.length; i++) {
1216        if (data.charAt(i) == '\ufffd') {
1217          ret.push(parser.decodePacket(data.substr(i + 1).substr(0, length)));
1218          i += Number(length) + 1;
1219          length = '';
1220        } else {
1221          length += data.charAt(i);
1222        }
1223      }
1224
1225      return ret;
1226    } else {
1227      return [parser.decodePacket(data)];
1228    }
1229  };
1230
1231})(
1232    'undefined' != typeof io ? io : module.exports
1233  , 'undefined' != typeof io ? io : module.parent.exports
1234);
1235/**
1236 * socket.io
1237 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
1238 * MIT Licensed
1239 */
1240
1241(function (exports, io) {
1242
1243  /**
1244   * Expose constructor.
1245   */
1246
1247  exports.Transport = Transport;
1248
1249  /**
1250   * This is the transport template for all supported transport methods.
1251   *
1252   * @constructor
1253   * @api public
1254   */
1255
1256  function Transport (socket, sessid) {
1257    this.socket = socket;
1258    this.sessid = sessid;
1259  };
1260
1261  /**
1262   * Apply EventEmitter mixin.
1263   */
1264
1265  io.util.mixin(Transport, io.EventEmitter);
1266
1267
1268  /**
1269   * Indicates whether heartbeats is enabled for this transport
1270   *
1271   * @api private
1272   */
1273
1274  Transport.prototype.heartbeats = function () {
1275    return true;
1276  };
1277
1278  /**
1279   * Handles the response from the server. When a new response is received
1280   * it will automatically update the timeout, decode the message and
1281   * forwards the response to the onMessage function for further processing.
1282   *
1283   * @param {String} data Response from the server.
1284   * @api private
1285   */
1286
1287  Transport.prototype.onData = function (data) {
1288    this.clearCloseTimeout();
1289
1290    // If the connection in currently open (or in a reopening state) reset the close
1291    // timeout since we have just received data. This check is necessary so
1292    // that we don't reset the timeout on an explicitly disconnected connection.
1293    if (this.socket.connected || this.socket.connecting || this.socket.reconnecting) {
1294      this.setCloseTimeout();
1295    }
1296
1297    if (data !== '') {
1298      // todo: we should only do decodePayload for xhr transports
1299      var msgs = io.parser.decodePayload(data);
1300
1301      if (msgs && msgs.length) {
1302        for (var i = 0, l = msgs.length; i < l; i++) {
1303          this.onPacket(msgs[i]);
1304        }
1305      }
1306    }
1307
1308    return this;
1309  };
1310
1311  /**
1312   * Handles packets.
1313   *
1314   * @api private
1315   */
1316
1317  Transport.prototype.onPacket = function (packet) {
1318    this.socket.setHeartbeatTimeout();
1319
1320    if (packet.type == 'heartbeat') {
1321      return this.onHeartbeat();
1322    }
1323
1324    if (packet.type == 'connect' && packet.endpoint == '') {
1325      this.onConnect();
1326    }
1327
1328    if (packet.type == 'error' && packet.advice == 'reconnect') {
1329      this.isOpen = false;
1330    }
1331
1332    this.socket.onPacket(packet);
1333
1334    return this;
1335  };
1336
1337  /**
1338   * Sets close timeout
1339   *
1340   * @api private
1341   */
1342
1343  Transport.prototype.setCloseTimeout = function () {
1344    if (!this.closeTimeout) {
1345      var self = this;
1346
1347      this.closeTimeout = setTimeout(function () {
1348        self.onDisconnect();
1349      }, this.socket.closeTimeout);
1350    }
1351  };
1352
1353  /**
1354   * Called when transport disconnects.
1355   *
1356   * @api private
1357   */
1358
1359  Transport.prototype.onDisconnect = function () {
1360    if (this.isOpen) this.close();
1361    this.clearTimeouts();
1362    this.socket.onDisconnect();
1363    return this;
1364  };
1365
1366  /**
1367   * Called when transport connects
1368   *
1369   * @api private
1370   */
1371
1372  Transport.prototype.onConnect = function () {
1373    this.socket.onConnect();
1374    return this;
1375  };
1376
1377  /**
1378   * Clears close timeout
1379   *
1380   * @api private
1381   */
1382
1383  Transport.prototype.clearCloseTimeout = function () {
1384    if (this.closeTimeout) {
1385      clearTimeout(this.closeTimeout);
1386      this.closeTimeout = null;
1387    }
1388  };
1389
1390  /**
1391   * Clear timeouts
1392   *
1393   * @api private
1394   */
1395
1396  Transport.prototype.clearTimeouts = function () {
1397    this.clearCloseTimeout();
1398
1399    if (this.reopenTimeout) {
1400      clearTimeout(this.reopenTimeout);
1401    }
1402  };
1403
1404  /**
1405   * Sends a packet
1406   *
1407   * @param {Object} packet object.
1408   * @api private
1409   */
1410
1411  Transport.prototype.packet = function (packet) {
1412    this.send(io.parser.encodePacket(packet));
1413  };
1414
1415  /**
1416   * Send the received heartbeat message back to server. So the server
1417   * knows we are still connected.
1418   *
1419   * @param {String} heartbeat Heartbeat response from the server.
1420   * @api private
1421   */
1422
1423  Transport.prototype.onHeartbeat = function (heartbeat) {
1424    this.packet({ type: 'heartbeat' });
1425  };
1426
1427  /**
1428   * Called when the transport opens.
1429   *
1430   * @api private
1431   */
1432
1433  Transport.prototype.onOpen = function () {
1434    this.isOpen = true;
1435    this.clearCloseTimeout();
1436    this.socket.onOpen();
1437  };
1438
1439  /**
1440   * Notifies the base when the connection with the Socket.IO server
1441   * has been disconnected.
1442   *
1443   * @api private
1444   */
1445
1446  Transport.prototype.onClose = function () {
1447    var self = this;
1448
1449    /* FIXME: reopen delay causing a infinit loop
1450    this.reopenTimeout = setTimeout(function () {
1451      self.open();
1452    }, this.socket.options['reopen delay']);*/
1453
1454    this.isOpen = false;
1455    this.socket.onClose();
1456    this.onDisconnect();
1457  };
1458
1459  /**
1460   * Generates a connection url based on the Socket.IO URL Protocol.
1461   * See <https://github.com/learnboost/socket.io-node/> for more details.
1462   *
1463   * @returns {String} Connection url
1464   * @api private
1465   */
1466
1467  Transport.prototype.prepareUrl = function () {
1468    var options = this.socket.options;
1469
1470    return this.scheme() + '://'
1471      + options.host + ':' + options.port + '/'
1472      + options.resource + '/' + io.protocol
1473      + '/' + this.name + '/' + this.sessid;
1474  };
1475
1476  /**
1477   * Checks if the transport is ready to start a connection.
1478   *
1479   * @param {Socket} socket The socket instance that needs a transport
1480   * @param {Function} fn The callback
1481   * @api private
1482   */
1483
1484  Transport.prototype.ready = function (socket, fn) {
1485    fn.call(this);
1486  };
1487})(
1488    'undefined' != typeof io ? io : module.exports
1489  , 'undefined' != typeof io ? io : module.parent.exports
1490);
1491/**
1492 * socket.io
1493 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
1494 * MIT Licensed
1495 */
1496
1497(function (exports, io, global) {
1498
1499  /**
1500   * Expose constructor.
1501   */
1502
1503  exports.Socket = Socket;
1504
1505  /**
1506   * Create a new `Socket.IO client` which can establish a persistent
1507   * connection with a Socket.IO enabled server.
1508   *
1509   * @api public
1510   */
1511
1512  function Socket (options) {
1513    this.options = {
1514        port: 80
1515      , secure: false
1516      , document: 'document' in global ? document : false
1517      , resource: 'socket.io'
1518      , transports: io.transports
1519      , 'connect timeout': 10000
1520      , 'try multiple transports': true
1521      , 'reconnect': true
1522      , 'reconnection delay': 500
1523      , 'reconnection limit': Infinity
1524      , 'reopen delay': 3000
1525      , 'max reconnection attempts': 10
1526      , 'sync disconnect on unload': false
1527      , 'auto connect': true
1528      , 'flash policy port': 10843
1529      , 'manualFlush': false
1530    };
1531
1532    io.util.merge(this.options, options);
1533
1534    this.connected = false;
1535    this.open = false;
1536    this.connecting = false;
1537    this.reconnecting = false;
1538    this.namespaces = {};
1539    this.buffer = [];
1540    this.doBuffer = false;
1541
1542    if (this.options['sync disconnect on unload'] &&
1543        (!this.isXDomain() || io.util.ua.hasCORS)) {
1544      var self = this;
1545      io.util.on(global, 'beforeunload', function () {
1546        self.disconnectSync();
1547      }, false);
1548    }
1549
1550    if (this.options['auto connect']) {
1551      this.connect();
1552    }
1553};
1554
1555  /**
1556   * Apply EventEmitter mixin.
1557   */
1558
1559  io.util.mixin(Socket, io.EventEmitter);
1560
1561  /**
1562   * Returns a namespace listener/emitter for this socket
1563   *
1564   * @api public
1565   */
1566
1567  Socket.prototype.of = function (name) {
1568    if (!this.namespaces[name]) {
1569      this.namespaces[name] = new io.SocketNamespace(this, name);
1570
1571      if (name !== '') {
1572        this.namespaces[name].packet({ type: 'connect' });
1573      }
1574    }
1575
1576    return this.namespaces[name];
1577  };
1578
1579  /**
1580   * Emits the given event to the Socket and all namespaces
1581   *
1582   * @api private
1583   */
1584
1585  Socket.prototype.publish = function () {
1586    this.emit.apply(this, arguments);
1587
1588    var nsp;
1589
1590    for (var i in this.namespaces) {
1591      if (this.namespaces.hasOwnProperty(i)) {
1592        nsp = this.of(i);
1593        nsp.$emit.apply(nsp, arguments);
1594      }
1595    }
1596  };
1597
1598  /**
1599   * Performs the handshake
1600   *
1601   * @api private
1602   */
1603
1604  function empty () { };
1605
1606  Socket.prototype.handshake = function (fn) {
1607    var self = this
1608      , options = this.options;
1609
1610    function complete (data) {
1611      if (data instanceof Error) {
1612        self.connecting = false;
1613        self.onError(data.message);
1614      } else {
1615        fn.apply(null, data.split(':'));
1616      }
1617    };
1618
1619    var url = [
1620          'http' + (options.secure ? 's' : '') + ':/'
1621        , options.host + ':' + options.port
1622        , options.resource
1623        , io.protocol
1624        , io.util.query(this.options.query, 't=' + +new Date)
1625      ].join('/');
1626
1627    if (this.isXDomain() && !io.util.ua.hasCORS) {
1628      var insertAt = document.getElementsByTagName('script')[0]
1629        , script = document.createElement('script');
1630
1631      script.src = url + '&jsonp=' + io.j.length;
1632      insertAt.parentNode.insertBefore(script, insertAt);
1633
1634      io.j.push(function (data) {
1635        complete(data);
1636        script.parentNode.removeChild(script);
1637      });
1638    } else {
1639      var xhr = io.util.request();
1640
1641      xhr.open('GET', url, true);
1642      if (this.isXDomain()) {
1643        xhr.withCredentials = true;
1644      }
1645      xhr.onreadystatechange = function () {
1646        if (xhr.readyState == 4) {
1647          xhr.onreadystatechange = empty;
1648
1649          if (xhr.status == 200) {
1650            complete(xhr.responseText);
1651          } else if (xhr.status == 403) {
1652            self.onError(xhr.responseText);
1653          } else {
1654            self.connecting = false;            
1655            !self.reconnecting && self.onError(xhr.responseText);
1656          }
1657        }
1658      };
1659      xhr.send(null);
1660    }
1661  };
1662
1663  /**
1664   * Find an available transport based on the options supplied in the constructor.
1665   *
1666   * @api private
1667   */
1668
1669  Socket.prototype.getTransport = function (override) {
1670    var transports = override || this.transports, match;
1671
1672    for (var i = 0, transport; transport = transports[i]; i++) {
1673      if (io.Transport[transport]
1674        && io.Transport[transport].check(this)
1675        && (!this.isXDomain() || io.Transport[transport].xdomainCheck(this))) {
1676        return new io.Transport[transport](this, this.sessionid);
1677      }
1678    }
1679
1680    return null;
1681  };
1682
1683  /**
1684   * Connects to the server.
1685   *
1686   * @param {Function} [fn] Callback.
1687   * @returns {io.Socket}
1688   * @api public
1689   */
1690
1691  Socket.prototype.connect = function (fn) {
1692    if (this.connecting) {
1693      return this;
1694    }
1695
1696    var self = this;
1697    self.connecting = true;
1698    
1699    this.handshake(function (sid, heartbeat, close, transports) {
1700      self.sessionid = sid;
1701      self.closeTimeout = close * 1000;
1702      self.heartbeatTimeout = heartbeat * 1000;
1703      if(!self.transports)
1704          self.transports = self.origTransports = (transports ? io.util.intersect(
1705              transports.split(',')
1706            , self.options.transports
1707          ) : self.options.transports);
1708
1709      self.setHeartbeatTimeout();
1710
1711      function connect (transports){
1712        if (self.transport) self.transport.clearTimeouts();
1713
1714        self.transport = self.getTransport(transports);
1715        if (!self.transport) return self.publish('connect_failed');
1716
1717        // once the transport is ready
1718        self.transport.ready(self, function () {
1719          self.connecting = true;
1720          self.publish('connecting', self.transport.name);
1721          self.transport.open();
1722
1723          if (self.options['connect timeout']) {
1724            self.connectTimeoutTimer = setTimeout(function () {
1725              if (!self.connected) {
1726                self.connecting = false;
1727
1728                if (self.options['try multiple transports']) {
1729                  var remaining = self.transports;
1730
1731                  while (remaining.length > 0 && remaining.splice(0,1)[0] !=
1732                         self.transport.name) {}
1733
1734                    if (remaining.length){
1735                      connect(remaining);
1736                    } else {
1737                      self.publish('connect_failed');
1738                    }
1739                }
1740              }
1741            }, self.options['connect timeout']);
1742          }
1743        });
1744      }
1745
1746      connect(self.transports);
1747
1748      self.once('connect', function (){
1749        clearTimeout(self.connectTimeoutTimer);
1750
1751        fn && typeof fn == 'function' && fn();
1752      });
1753    });
1754
1755    return this;
1756  };
1757
1758  /**
1759   * Clears and sets a new heartbeat timeout using the value given by the
1760   * server during the handshake.
1761   *
1762   * @api private
1763   */
1764
1765  Socket.prototype.setHeartbeatTimeout = function () {
1766    clearTimeout(this.heartbeatTimeoutTimer);
1767    if(this.transport && !this.transport.heartbeats()) return;
1768
1769    var self = this;
1770    this.heartbeatTimeoutTimer = setTimeout(function () {
1771      self.transport.onClose();
1772    }, this.heartbeatTimeout);
1773  };
1774
1775  /**
1776   * Sends a message.
1777   *
1778   * @param {Object} data packet.
1779   * @returns {io.Socket}
1780   * @api public
1781   */
1782
1783  Socket.prototype.packet = function (data) {
1784    if (this.connected && !this.doBuffer) {
1785      this.transport.packet(data);
1786    } else {
1787      this.buffer.push(data);
1788    }
1789
1790    return this;
1791  };
1792
1793  /**
1794   * Sets buffer state
1795   *
1796   * @api private
1797   */
1798
1799  Socket.prototype.setBuffer = function (v) {
1800    this.doBuffer = v;
1801
1802    if (!v && this.connected && this.buffer.length) {
1803      if (!this.options['manualFlush']) {
1804        this.flushBuffer();
1805      }
1806    }
1807  };
1808
1809  /**
1810   * Flushes the buffer data over the wire.
1811   * To be invoked manually when 'manualFlush' is set to true.
1812   *
1813   * @api public
1814   */
1815
1816  Socket.prototype.flushBuffer = function() {
1817    this.transport.payload(this.buffer);
1818    this.buffer = [];
1819  };
1820  
1821
1822  /**
1823   * Disconnect the established connect.
1824   *
1825   * @returns {io.Socket}
1826   * @api public
1827   */
1828
1829  Socket.prototype.disconnect = function () {
1830    if (this.connected || this.connecting) {
1831      if (this.open) {
1832        this.of('').packet({ type: 'disconnect' });
1833      }
1834
1835      // handle disconnection immediately
1836      this.onDisconnect('booted');
1837    }
1838
1839    return this;
1840  };
1841
1842  /**
1843   * Disconnects the socket with a sync XHR.
1844   *
1845   * @api private
1846   */
1847
1848  Socket.prototype.disconnectSync = function () {
1849    // ensure disconnection
1850    var xhr = io.util.request();
1851    var uri = [
1852        'http' + (this.options.secure ? 's' : '') + ':/'
1853      , this.options.host + ':' + this.options.port
1854      , this.options.resource
1855      , io.protocol
1856      , ''
1857      , this.sessionid
1858    ].join('/') + '/?disconnect=1';
1859
1860    xhr.open('GET', uri, false);
1861    xhr.send(null);
1862
1863    // handle disconnection immediately
1864    this.onDisconnect('booted');
1865  };
1866
1867  /**
1868   * Check if we need to use cross domain enabled transports. Cross domain would
1869   * be a different port or different domain name.
1870   *
1871   * @returns {Boolean}
1872   * @api private
1873   */
1874
1875  Socket.prototype.isXDomain = function () {
1876
1877    var port = global.location.port ||
1878      ('https:' == global.location.protocol ? 443 : 80);
1879
1880    return this.options.host !== global.location.hostname 
1881      || this.options.port != port;
1882  };
1883
1884  /**
1885   * Called upon handshake.
1886   *
1887   * @api private
1888   */
1889
1890  Socket.prototype.onConnect = function () {
1891    if (!this.connected) {
1892      this.connected = true;
1893      this.connecting = false;
1894      if (!this.doBuffer) {
1895        // make sure to flush the buffer
1896        this.setBuffer(false);
1897      }
1898      this.emit('connect');
1899    }
1900  };
1901
1902  /**
1903   * Called when the transport opens
1904   *
1905   * @api private
1906   */
1907
1908  Socket.prototype.onOpen = function () {
1909    this.open = true;
1910  };
1911
1912  /**
1913   * Called when the transport closes.
1914   *
1915   * @api private
1916   */
1917
1918  Socket.prototype.onClose = function () {
1919    this.open = false;
1920    clearTimeout(this.heartbeatTimeoutTimer);
1921  };
1922
1923  /**
1924   * Called when the transport first opens a connection
1925   *
1926   * @param text
1927   */
1928
1929  Socket.prototype.onPacket = function (packet) {
1930    this.of(packet.endpoint).onPacket(packet);
1931  };
1932
1933  /**
1934   * Handles an error.
1935   *
1936   * @api private
1937   */
1938
1939  Socket.prototype.onError = function (err) {
1940    if (err && err.advice) {
1941      if (err.advice === 'reconnect' && (this.connected || this.connecting)) {
1942        this.disconnect();
1943        if (this.options.reconnect) {
1944          this.reconnect();
1945        }
1946      }
1947    }
1948
1949    this.publish('error', err && err.reason ? err.reason : err);
1950  };
1951
1952  /**
1953   * Called when the transport disconnects.
1954   *
1955   * @api private
1956   */
1957
1958  Socket.prototype.onDisconnect = function (reason) {
1959    var wasConnected = this.connected
1960      , wasConnecting = this.connecting;
1961
1962    this.connected = false;
1963    this.connecting = false;
1964    this.open = false;
1965
1966    if (wasConnected || wasConnecting) {
1967      this.transport.close();
1968      this.transport.clearTimeouts();
1969      if (wasConnected) {
1970        this.publish('disconnect', reason);
1971
1972        if ('booted' != reason && this.options.reconnect && !this.reconnecting) {
1973          this.reconnect();
1974        }
1975      }
1976    }
1977  };
1978
1979  /**
1980   * Called upon reconnection.
1981   *
1982   * @api private
1983   */
1984
1985  Socket.prototype.reconnect = function () {
1986    this.reconnecting = true;
1987    this.reconnectionAttempts = 0;
1988    this.reconnectionDelay = this.options['reconnection delay'];
1989
1990    var self = this
1991      , maxAttempts = this.options['max reconnection attempts']
1992      , tryMultiple = this.options['try multiple transports']
1993      , limit = this.options['reconnection limit'];
1994
1995    function reset () {
1996      if (self.connected) {
1997        for (var i in self.namespaces) {
1998          if (self.namespaces.hasOwnProperty(i) && '' !== i) {
1999              self.namespaces[i].packet({ type: 'connect' });
2000          }
2001        }
2002        self.publish('reconnect', self.transport.name, self.reconnectionAttempts);
2003      }
2004
2005      clearTimeout(self.reconnectionTimer);
2006
2007      self.removeListener('connect_failed', maybeReconnect);
2008      self.removeListener('connect', maybeReconnect);
2009
2010      self.reconnecting = false;
2011
2012      delete self.reconnectionAttempts;
2013      delete self.reconnectionDelay;
2014      delete self.reconnectionTimer;
2015      delete self.redoTransports;
2016
2017      self.options['try multiple transports'] = tryMultiple;
2018    };
2019
2020    function maybeReconnect () {
2021      if (!self.reconnecting) {
2022        return;
2023      }
2024
2025      if (self.connected) {
2026        return reset();
2027      };
2028
2029      if (self.connecting && self.reconnecting) {
2030        return self.reconnectionTimer = setTimeout(maybeReconnect, 1000);
2031      }
2032
2033      if (self.reconnectionAttempts++ >= maxAttempts) {
2034        if (!self.redoTransports) {
2035          self.on('connect_failed', maybeReconnect);
2036          self.options['try multiple transports'] = true;
2037          self.transports = self.origTransports;
2038          self.transport = self.getTransport();
2039          self.redoTransports = true;
2040          self.connect();
2041        } else {
2042          self.publish('reconnect_failed');
2043          reset();
2044        }
2045      } else {
2046        if (self.reconnectionDelay < limit) {
2047          self.reconnectionDelay *= 2; // exponential back off
2048        }
2049
2050        self.connect();
2051        self.publish('reconnecting', self.reconnectionDelay, self.reconnectionAttempts);
2052        self.reconnectionTimer = setTimeout(maybeReconnect, self.reconnectionDelay);
2053      }
2054    };
2055
2056    this.options['try multiple transports'] = false;
2057    this.reconnectionTimer = setTimeout(maybeReconnect, this.reconnectionDelay);
2058
2059    this.on('connect', maybeReconnect);
2060  };
2061
2062})(
2063    'undefined' != typeof io ? io : module.exports
2064  , 'undefined' != typeof io ? io : module.parent.exports
2065  , this
2066);
2067/**
2068 * socket.io
2069 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
2070 * MIT Licensed
2071 */
2072
2073(function (exports, io) {
2074
2075  /**
2076   * Expose constructor.
2077   */
2078
2079  exports.SocketNamespace = SocketNamespace;
2080
2081  /**
2082   * Socket namespace constructor.
2083   *
2084   * @constructor
2085   * @api public
2086   */
2087
2088  function SocketNamespace (socket, name) {
2089    this.socket = socket;
2090    this.name = name || '';
2091    this.flags = {};
2092    this.json = new Flag(this, 'json');
2093    this.ackPackets = 0;
2094    this.acks = {};
2095  };
2096
2097  /**
2098   * Apply EventEmitter mixin.
2099   */
2100
2101  io.util.mixin(SocketNamespace, io.EventEmitter);
2102
2103  /**
2104   * Copies emit since we override it
2105   *
2106   * @api private
2107   */
2108
2109  SocketNamespace.prototype.$emit = io.EventEmitter.prototype.emit;
2110
2111  /**
2112   * Creates a new namespace, by proxying the request to the socket. This
2113   * allows us to use the synax as we do on the server.
2114   *
2115   * @api public
2116   */
2117
2118  SocketNamespace.prototype.of = function () {
2119    return this.socket.of.apply(this.socket, arguments);
2120  };
2121
2122  /**
2123   * Sends a packet.
2124   *
2125   * @api private
2126   */
2127
2128  SocketNamespace.prototype.packet = function (packet) {
2129    packet.endpoint = this.name;
2130    this.socket.packet(packet);
2131    this.flags = {};
2132    return this;
2133  };
2134
2135  /**
2136   * Sends a message
2137   *
2138   * @api public
2139   */
2140
2141  SocketNamespace.prototype.send = function (data, fn) {
2142    var packet = {
2143        type: this.flags.json ? 'json' : 'message'
2144      , data: data
2145    };
2146
2147    if ('function' == typeof fn) {
2148      packet.id = ++this.ackPackets;
2149      packet.ack = true;
2150      this.acks[packet.id] = fn;
2151    }
2152
2153    return this.packet(packet);
2154  };
2155
2156  /**
2157   * Emits an event
2158   *
2159   * @api public
2160   */
2161  
2162  SocketNamespace.prototype.emit = function (name) {
2163    var args = Array.prototype.slice.call(arguments, 1)
2164      , lastArg = args[args.length - 1]
2165      , packet = {
2166            type: 'event'
2167          , name: name
2168        };
2169
2170    if ('function' == typeof lastArg) {
2171      packet.id = ++this.ackPackets;
2172      packet.ack = 'data';
2173      this.acks[packet.id] = lastArg;
2174      args = args.slice(0, args.length - 1);
2175    }
2176
2177    packet.args = args;
2178
2179    return this.packet(packet);
2180  };
2181
2182  /**
2183   * Disconnects the namespace
2184   *
2185   * @api private
2186   */
2187
2188  SocketNamespace.prototype.disconnect = function () {
2189    if (this.name === '') {
2190      this.socket.disconnect();
2191    } else {
2192      this.packet({ type: 'd

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