text: /******/ (function(modules) { // webpackBootstrap
  /******/ 	// The module cache
  /******/ 	var installedModules = {};
  
  /******/ 	// The require function
  /******/ 	function __webpack_require__(moduleId) {
  
  /******/ 		// Check if module is in cache
  /******/ 		if(installedModules[moduleId])
  /******/ 			return installedModules[moduleId].exports;
  
  /******/ 		// Create a new module (and put it into the cache)
  /******/ 		var module = installedModules[moduleId] = {
  /******/ 			exports: {},
  /******/ 			id: moduleId,
  /******/ 			loaded: false
  /******/ 		};
  
  /******/ 		// Execute the module function
  /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  
  /******/ 		// Flag the module as loaded
  /******/ 		module.loaded = true;
  
  /******/ 		// Return the exports of the module
  /******/ 		return module.exports;
  /******/ 	}
  
  
  /******/ 	// expose the modules object (__webpack_modules__)
  /******/ 	__webpack_require__.m = modules;
  
  /******/ 	// expose the module cache
  /******/ 	__webpack_require__.c = installedModules;
  
  /******/ 	// __webpack_public_path__
  /******/ 	__webpack_require__.p = "";
  
  /******/ 	// Load entry module and return exports
  /******/ 	return __webpack_require__(0);
  /******/ })
  /************************************************************************/
  /******/ ([
  /* 0 */
  /***/ function(module, exports, __webpack_require__) {
  
  	var io = __webpack_require__(1);
  	var Howl = __webpack_require__(56).Howl;
  
  	var bitcoin_url = __webpack_require__(57);
  
  	var socket = io('http://ec2-54-169-242-142.ap-southeast-1.compute.amazonaws.com');
  
  	var sounds = {
  	    'bitcoin': new Howl({
  	        src: [bitcoin_url]
  	    })
  	};
  
  	socket.on('play-sound', function (sound_name) {
  	    if (sounds.hasOwnProperty(sound_name)) {
  	        sounds[sound_name].play();
  	    }
  	});
  
  /***/ },
  /* 1 */
  /***/ function(module, exports, __webpack_require__) {
  
  	
  	/**
  	 * Module dependencies.
  	 */
  
  	var url = __webpack_require__(2);
  	var parser = __webpack_require__(8);
  	var Manager = __webpack_require__(19);
  	var debug = __webpack_require__(4)('socket.io-client');
  
  	/**
  	 * Module exports.
  	 */
  
  	module.exports = exports = lookup;
  
  	/**
  	 * Managers cache.
  	 */
  
  	var cache = exports.managers = {};
  
  	/**
  	 * Looks up an existing `Manager` for multiplexing.
  	 * If the user summons:
  	 *
  	 *   `io('http://localhost/a');`
  	 *   `io('http://localhost/b');`
  	 *
  	 * We reuse the existing instance based on same scheme/port/host,
  	 * and we initialize sockets for each namespace.
  	 *
  	 * @api public
  	 */
  
  	function lookup (uri, opts) {
  	  if (typeof uri === 'object') {
  	    opts = uri;
  	    uri = undefined;
  	  }
  
  	  opts = opts || {};
  
  	  var parsed = url(uri);
  	  var source = parsed.source;
  	  var id = parsed.id;
  	  var path = parsed.path;
  	  var sameNamespace = cache[id] && path in cache[id].nsps;
  	  var newConnection = opts.forceNew || opts['force new connection'] ||
  	                      false === opts.multiplex || sameNamespace;
  
  	  var io;
  
  	  if (newConnection) {
  	    debug('ignoring socket cache for %s', source);
  	    io = Manager(source, opts);
  	  } else {
  	    if (!cache[id]) {
  	      debug('new io instance for %s', source);
  	      cache[id] = Manager(source, opts);
  	    }
  	    io = cache[id];
  	  }
  	  if (parsed.query && !opts.query) {
  	    opts.query = parsed.query;
  	  } else if (opts && 'object' === typeof opts.query) {
  	    opts.query = encodeQueryString(opts.query);
  	  }
  	  return io.socket(parsed.path, opts);
  	}
  	/**
  	 *  Helper method to parse query objects to string.
  	 * @param {object} query
  	 * @returns {string}
  	 */
  	function encodeQueryString (obj) {
  	  var str = [];
  	  for (var p in obj) {
  	    if (obj.hasOwnProperty(p)) {
  	      str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
  	    }
  	  }
  	  return str.join('&');
  	}
  	/**
  	 * Protocol version.
  	 *
  	 * @api public
  	 */
  
  	exports.protocol = parser.protocol;
  
  	/**
  	 * `connect`.
  	 *
  	 * @param {String} uri
  	 * @api public
  	 */
  
  	exports.connect = lookup;
  
  	/**
  	 * Expose constructors for standalone build.
  	 *
  	 * @api public
  	 */
  
  	exports.Manager = __webpack_require__(19);
  	exports.Socket = __webpack_require__(49);
  
  
  /***/ },
  /* 2 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {
  	/**
  	 * Module dependencies.
  	 */
  
  	var parseuri = __webpack_require__(3);
  	var debug = __webpack_require__(4)('socket.io-client:url');
  
  	/**
  	 * Module exports.
  	 */
  
  	module.exports = url;
  
  	/**
  	 * URL parser.
  	 *
  	 * @param {String} url
  	 * @param {Object} An object meant to mimic window.location.
  	 *                 Defaults to window.location.
  	 * @api public
  	 */
  
  	function url (uri, loc) {
  	  var obj = uri;
  
  	  // default to window.location
  	  loc = loc || global.location;
  	  if (null == uri) uri = loc.protocol + '//' + loc.host;
  
  	  // relative path support
  	  if ('string' === typeof uri) {
  	    if ('/' === uri.charAt(0)) {
  	      if ('/' === uri.charAt(1)) {
  	        uri = loc.protocol + uri;
  	      } else {
  	        uri = loc.host + uri;
  	      }
  	    }
  
  	    if (!/^(https?|wss?):\/\//.test(uri)) {
  	      debug('protocol-less url %s', uri);
  	      if ('undefined' !== typeof loc) {
  	        uri = loc.protocol + '//' + uri;
  	      } else {
  	        uri = 'https://' + uri;
  	      }
  	    }
  
  	    // parse
  	    debug('parse %s', uri);
  	    obj = parseuri(uri);
  	  }
  
  	  // make sure we treat `localhost:80` and `localhost` equally
  	  if (!obj.port) {
  	    if (/^(http|ws)$/.test(obj.protocol)) {
  	      obj.port = '80';
  	    } else if (/^(http|ws)s$/.test(obj.protocol)) {
  	      obj.port = '443';
  	    }
  	  }
  
  	  obj.path = obj.path || '/';
  
  	  var ipv6 = obj.host.indexOf(':') !== -1;
  	  var host = ipv6 ? '[' + obj.host + ']' : obj.host;
  
  	  // define unique id
  	  obj.id = obj.protocol + '://' + host + ':' + obj.port;
  	  // define href
  	  obj.href = obj.protocol + '://' + host + (loc && loc.port === obj.port ? '' : (':' + obj.port));
  
  	  return obj;
  	}
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 3 */
  /***/ function(module, exports) {
  
  	/**
  	 * Parses an URI
  	 *
  	 * @author Steven Levithan <stevenlevithan.com> (MIT license)
  	 * @api private
  	 */
  
  	var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
  
  	var parts = [
  	    'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
  	];
  
  	module.exports = function parseuri(str) {
  	    var src = str,
  	        b = str.indexOf('['),
  	        e = str.indexOf(']');
  
  	    if (b != -1 && e != -1) {
  	        str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
  	    }
  
  	    var m = re.exec(str || ''),
  	        uri = {},
  	        i = 14;
  
  	    while (i--) {
  	        uri[parts[i]] = m[i] || '';
  	    }
  
  	    if (b != -1 && e != -1) {
  	        uri.source = src;
  	        uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
  	        uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
  	        uri.ipv6uri = true;
  	    }
  
  	    return uri;
  	};
  
  
  /***/ },
  /* 4 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(process) {
  	/**
  	 * This is the web browser implementation of `debug()`.
  	 *
  	 * Expose `debug()` as the module.
  	 */
  
  	exports = module.exports = __webpack_require__(6);
  	exports.log = log;
  	exports.formatArgs = formatArgs;
  	exports.save = save;
  	exports.load = load;
  	exports.useColors = useColors;
  	exports.storage = 'undefined' != typeof chrome
  	               && 'undefined' != typeof chrome.storage
  	                  ? chrome.storage.local
  	                  : localstorage();
  
  	/**
  	 * Colors.
  	 */
  
  	exports.colors = [
  	  'lightseagreen',
  	  'forestgreen',
  	  'goldenrod',
  	  'dodgerblue',
  	  'darkorchid',
  	  'crimson'
  	];
  
  	/**
  	 * Currently only WebKit-based Web Inspectors, Firefox >= v31,
  	 * and the Firebug extension (any Firefox version) are known
  	 * to support "%c" CSS customizations.
  	 *
  	 * TODO: add a `localStorage` variable to explicitly enable/disable colors
  	 */
  
  	function useColors() {
  	  // is webkit? http://stackoverflow.com/a/16459606/376773
  	  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
  	  return (typeof document !== 'undefined' && 'WebkitAppearance' in document.documentElement.style) ||
  	    // is firebug? http://stackoverflow.com/a/398120/376773
  	    (window.console && (console.firebug || (console.exception && console.table))) ||
  	    // is firefox >= v31?
  	    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
  	    (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
  	}
  
  	/**
  	 * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
  	 */
  
  	exports.formatters.j = function(v) {
  	  try {
  	    return JSON.stringify(v);
  	  } catch (err) {
  	    return '[UnexpectedJSONParseError]: ' + err.message;
  	  }
  	};
  
  
  	/**
  	 * Colorize log arguments if enabled.
  	 *
  	 * @api public
  	 */
  
  	function formatArgs() {
  	  var args = arguments;
  	  var useColors = this.useColors;
  
  	  args[0] = (useColors ? '%c' : '')
  	    + this.namespace
  	    + (useColors ? ' %c' : ' ')
  	    + args[0]
  	    + (useColors ? '%c ' : ' ')
  	    + '+' + exports.humanize(this.diff);
  
  	  if (!useColors) return args;
  
  	  var c = 'color: ' + this.color;
  	  args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
  
  	  // the final "%c" is somewhat tricky, because there could be other
  	  // arguments passed either before or after the %c, so we need to
  	  // figure out the correct index to insert the CSS into
  	  var index = 0;
  	  var lastC = 0;
  	  args[0].replace(/%[a-z%]/g, function(match) {
  	    if ('%%' === match) return;
  	    index++;
  	    if ('%c' === match) {
  	      // we only are interested in the *last* %c
  	      // (the user may have provided their own)
  	      lastC = index;
  	    }
  	  });
  
  	  args.splice(lastC, 0, c);
  	  return args;
  	}
  
  	/**
  	 * Invokes `console.log()` when available.
  	 * No-op when `console.log` is not a "function".
  	 *
  	 * @api public
  	 */
  
  	function log() {
  	  // this hackery is required for IE8/9, where
  	  // the `console.log` function doesn't have 'apply'
  	  return 'object' === typeof console
  	    && console.log
  	    && Function.prototype.apply.call(console.log, console, arguments);
  	}
  
  	/**
  	 * Save `namespaces`.
  	 *
  	 * @param {String} namespaces
  	 * @api private
  	 */
  
  	function save(namespaces) {
  	  try {
  	    if (null == namespaces) {
  	      exports.storage.removeItem('debug');
  	    } else {
  	      exports.storage.debug = namespaces;
  	    }
  	  } catch(e) {}
  	}
  
  	/**
  	 * Load `namespaces`.
  	 *
  	 * @return {String} returns the previously persisted debug modes
  	 * @api private
  	 */
  
  	function load() {
  	  var r;
  	  try {
  	    return exports.storage.debug;
  	  } catch(e) {}
  
  	  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
  	  if (typeof process !== 'undefined' && 'env' in process) {
  	    return process.env.DEBUG;
  	  }
  	}
  
  	/**
  	 * Enable namespaces listed in `localStorage.debug` initially.
  	 */
  
  	exports.enable(load());
  
  	/**
  	 * Localstorage attempts to return the localstorage.
  	 *
  	 * This is necessary because safari throws
  	 * when a user disables cookies/localstorage
  	 * and you attempt to access it.
  	 *
  	 * @return {LocalStorage}
  	 * @api private
  	 */
  
  	function localstorage(){
  	  try {
  	    return window.localStorage;
  	  } catch (e) {}
  	}
  
  	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5)))
  
  /***/ },
  /* 5 */
  /***/ function(module, exports) {
  
  	// shim for using process in browser
  	var process = module.exports = {};
  
  	// cached from whatever global is present so that test runners that stub it
  	// don't break things.  But we need to wrap it in a try catch in case it is
  	// wrapped in strict mode code which doesn't define any globals.  It's inside a
  	// function because try/catches deoptimize in certain engines.
  
  	var cachedSetTimeout;
  	var cachedClearTimeout;
  
  	function defaultSetTimout() {
  	    throw new Error('setTimeout has not been defined');
  	}
  	function defaultClearTimeout () {
  	    throw new Error('clearTimeout has not been defined');
  	}
  	(function () {
  	    try {
  	        if (typeof setTimeout === 'function') {
  	            cachedSetTimeout = setTimeout;
  	        } else {
  	            cachedSetTimeout = defaultSetTimout;
  	        }
  	    } catch (e) {
  	        cachedSetTimeout = defaultSetTimout;
  	    }
  	    try {
  	        if (typeof clearTimeout === 'function') {
  	            cachedClearTimeout = clearTimeout;
  	        } else {
  	            cachedClearTimeout = defaultClearTimeout;
  	        }
  	    } catch (e) {
  	        cachedClearTimeout = defaultClearTimeout;
  	    }
  	} ())
  	function runTimeout(fun) {
  	    if (cachedSetTimeout === setTimeout) {
  	        //normal enviroments in sane situations
  	        return setTimeout(fun, 0);
  	    }
  	    // if setTimeout wasn't available but was latter defined
  	    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
  	        cachedSetTimeout = setTimeout;
  	        return setTimeout(fun, 0);
  	    }
  	    try {
  	        // when when somebody has screwed with setTimeout but no I.E. maddness
  	        return cachedSetTimeout(fun, 0);
  	    } catch(e){
  	        try {
  	            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
  	            return cachedSetTimeout.call(null, fun, 0);
  	        } catch(e){
  	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
  	            return cachedSetTimeout.call(this, fun, 0);
  	        }
  	    }
  
  
  	}
  	function runClearTimeout(marker) {
  	    if (cachedClearTimeout === clearTimeout) {
  	        //normal enviroments in sane situations
  	        return clearTimeout(marker);
  	    }
  	    // if clearTimeout wasn't available but was latter defined
  	    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
  	        cachedClearTimeout = clearTimeout;
  	        return clearTimeout(marker);
  	    }
  	    try {
  	        // when when somebody has screwed with setTimeout but no I.E. maddness
  	        return cachedClearTimeout(marker);
  	    } catch (e){
  	        try {
  	            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
  	            return cachedClearTimeout.call(null, marker);
  	        } catch (e){
  	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
  	            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
  	            return cachedClearTimeout.call(this, marker);
  	        }
  	    }
  
  
  
  	}
  	var queue = [];
  	var draining = false;
  	var currentQueue;
  	var queueIndex = -1;
  
  	function cleanUpNextTick() {
  	    if (!draining || !currentQueue) {
  	        return;
  	    }
  	    draining = false;
  	    if (currentQueue.length) {
  	        queue = currentQueue.concat(queue);
  	    } else {
  	        queueIndex = -1;
  	    }
  	    if (queue.length) {
  	        drainQueue();
  	    }
  	}
  
  	function drainQueue() {
  	    if (draining) {
  	        return;
  	    }
  	    var timeout = runTimeout(cleanUpNextTick);
  	    draining = true;
  
  	    var len = queue.length;
  	    while(len) {
  	        currentQueue = queue;
  	        queue = [];
  	        while (++queueIndex < len) {
  	            if (currentQueue) {
  	                currentQueue[queueIndex].run();
  	            }
  	        }
  	        queueIndex = -1;
  	        len = queue.length;
  	    }
  	    currentQueue = null;
  	    draining = false;
  	    runClearTimeout(timeout);
  	}
  
  	process.nextTick = function (fun) {
  	    var args = new Array(arguments.length - 1);
  	    if (arguments.length > 1) {
  	        for (var i = 1; i < arguments.length; i++) {
  	            args[i - 1] = arguments[i];
  	        }
  	    }
  	    queue.push(new Item(fun, args));
  	    if (queue.length === 1 && !draining) {
  	        runTimeout(drainQueue);
  	    }
  	};
  
  	// v8 likes predictible objects
  	function Item(fun, array) {
  	    this.fun = fun;
  	    this.array = array;
  	}
  	Item.prototype.run = function () {
  	    this.fun.apply(null, this.array);
  	};
  	process.title = 'browser';
  	process.browser = true;
  	process.env = {};
  	process.argv = [];
  	process.version = ''; // empty string to avoid regexp issues
  	process.versions = {};
  
  	function noop() {}
  
  	process.on = noop;
  	process.addListener = noop;
  	process.once = noop;
  	process.off = noop;
  	process.removeListener = noop;
  	process.removeAllListeners = noop;
  	process.emit = noop;
  
  	process.binding = function (name) {
  	    throw new Error('process.binding is not supported');
  	};
  
  	process.cwd = function () { return '/' };
  	process.chdir = function (dir) {
  	    throw new Error('process.chdir is not supported');
  	};
  	process.umask = function() { return 0; };
  
  
  /***/ },
  /* 6 */
  /***/ function(module, exports, __webpack_require__) {
  
  	
  	/**
  	 * This is the common logic for both the Node.js and web browser
  	 * implementations of `debug()`.
  	 *
  	 * Expose `debug()` as the module.
  	 */
  
  	exports = module.exports = debug.debug = debug;
  	exports.coerce = coerce;
  	exports.disable = disable;
  	exports.enable = enable;
  	exports.enabled = enabled;
  	exports.humanize = __webpack_require__(7);
  
  	/**
  	 * The currently active debug mode names, and names to skip.
  	 */
  
  	exports.names = [];
  	exports.skips = [];
  
  	/**
  	 * Map of special "%n" handling functions, for the debug "format" argument.
  	 *
  	 * Valid key names are a single, lowercased letter, i.e. "n".
  	 */
  
  	exports.formatters = {};
  
  	/**
  	 * Previously assigned color.
  	 */
  
  	var prevColor = 0;
  
  	/**
  	 * Previous log timestamp.
  	 */
  
  	var prevTime;
  
  	/**
  	 * Select a color.
  	 *
  	 * @return {Number}
  	 * @api private
  	 */
  
  	function selectColor() {
  	  return exports.colors[prevColor++ % exports.colors.length];
  	}
  
  	/**
  	 * Create a debugger with the given `namespace`.
  	 *
  	 * @param {String} namespace
  	 * @return {Function}
  	 * @api public
  	 */
  
  	function debug(namespace) {
  
  	  // define the `disabled` version
  	  function disabled() {
  	  }
  	  disabled.enabled = false;
  
  	  // define the `enabled` version
  	  function enabled() {
  
  	    var self = enabled;
  
  	    // set `diff` timestamp
  	    var curr = +new Date();
  	    var ms = curr - (prevTime || curr);
  	    self.diff = ms;
  	    self.prev = prevTime;
  	    self.curr = curr;
  	    prevTime = curr;
  
  	    // add the `color` if not set
  	    if (null == self.useColors) self.useColors = exports.useColors();
  	    if (null == self.color && self.useColors) self.color = selectColor();
  
  	    var args = new Array(arguments.length);
  	    for (var i = 0; i < args.length; i++) {
  	      args[i] = arguments[i];
  	    }
  
  	    args[0] = exports.coerce(args[0]);
  
  	    if ('string' !== typeof args[0]) {
  	      // anything else let's inspect with %o
  	      args = ['%o'].concat(args);
  	    }
  
  	    // apply any `formatters` transformations
  	    var index = 0;
  	    args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
  	      // if we encounter an escaped % then don't increase the array index
  	      if (match === '%%') return match;
  	      index++;
  	      var formatter = exports.formatters[format];
  	      if ('function' === typeof formatter) {
  	        var val = args[index];
  	        match = formatter.call(self, val);
  
  	        // now we need to remove `args[index]` since it's inlined in the `format`
  	        args.splice(index, 1);
  	        index--;
  	      }
  	      return match;
  	    });
  
  	    // apply env-specific formatting
  	    args = exports.formatArgs.apply(self, args);
  
  	    var logFn = enabled.log || exports.log || console.log.bind(console);
  	    logFn.apply(self, args);
  	  }
  	  enabled.enabled = true;
  
  	  var fn = exports.enabled(namespace) ? enabled : disabled;
  
  	  fn.namespace = namespace;
  
  	  return fn;
  	}
  
  	/**
  	 * Enables a debug mode by namespaces. This can include modes
  	 * separated by a colon and wildcards.
  	 *
  	 * @param {String} namespaces
  	 * @api public
  	 */
  
  	function enable(namespaces) {
  	  exports.save(namespaces);
  
  	  var split = (namespaces || '').split(/[\s,]+/);
  	  var len = split.length;
  
  	  for (var i = 0; i < len; i++) {
  	    if (!split[i]) continue; // ignore empty strings
  	    namespaces = split[i].replace(/[\\^$+?.()|[\]{}]/g, '\\$&').replace(/\*/g, '.*?');
  	    if (namespaces[0] === '-') {
  	      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
  	    } else {
  	      exports.names.push(new RegExp('^' + namespaces + '$'));
  	    }
  	  }
  	}
  
  	/**
  	 * Disable debug output.
  	 *
  	 * @api public
  	 */
  
  	function disable() {
  	  exports.enable('');
  	}
  
  	/**
  	 * Returns true if the given mode name is enabled, false otherwise.
  	 *
  	 * @param {String} name
  	 * @return {Boolean}
  	 * @api public
  	 */
  
  	function enabled(name) {
  	  var i, len;
  	  for (i = 0, len = exports.skips.length; i < len; i++) {
  	    if (exports.skips[i].test(name)) {
  	      return false;
  	    }
  	  }
  	  for (i = 0, len = exports.names.length; i < len; i++) {
  	    if (exports.names[i].test(name)) {
  	      return true;
  	    }
  	  }
  	  return false;
  	}
  
  	/**
  	 * Coerce `val`.
  	 *
  	 * @param {Mixed} val
  	 * @return {Mixed}
  	 * @api private
  	 */
  
  	function coerce(val) {
  	  if (val instanceof Error) return val.stack || val.message;
  	  return val;
  	}
  
  
  /***/ },
  /* 7 */
  /***/ function(module, exports) {
  
  	/**
  	 * Helpers.
  	 */
  
  	var s = 1000
  	var m = s * 60
  	var h = m * 60
  	var d = h * 24
  	var y = d * 365.25
  
  	/**
  	 * Parse or format the given `val`.
  	 *
  	 * Options:
  	 *
  	 *  - `long` verbose formatting [false]
  	 *
  	 * @param {String|Number} val
  	 * @param {Object} options
  	 * @throws {Error} throw an error if val is not a non-empty string or a number
  	 * @return {String|Number}
  	 * @api public
  	 */
  
  	module.exports = function (val, options) {
  	  options = options || {}
  	  var type = typeof val
  	  if (type === 'string' && val.length > 0) {
  	    return parse(val)
  	  } else if (type === 'number' && isNaN(val) === false) {
  	    return options.long ?
  				fmtLong(val) :
  				fmtShort(val)
  	  }
  	  throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val))
  	}
  
  	/**
  	 * Parse the given `str` and return milliseconds.
  	 *
  	 * @param {String} str
  	 * @return {Number}
  	 * @api private
  	 */
  
  	function parse(str) {
  	  str = String(str)
  	  if (str.length > 10000) {
  	    return
  	  }
  	  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str)
  	  if (!match) {
  	    return
  	  }
  	  var n = parseFloat(match[1])
  	  var type = (match[2] || 'ms').toLowerCase()
  	  switch (type) {
  	    case 'years':
  	    case 'year':
  	    case 'yrs':
  	    case 'yr':
  	    case 'y':
  	      return n * y
  	    case 'days':
  	    case 'day':
  	    case 'd':
  	      return n * d
  	    case 'hours':
  	    case 'hour':
  	    case 'hrs':
  	    case 'hr':
  	    case 'h':
  	      return n * h
  	    case 'minutes':
  	    case 'minute':
  	    case 'mins':
  	    case 'min':
  	    case 'm':
  	      return n * m
  	    case 'seconds':
  	    case 'second':
  	    case 'secs':
  	    case 'sec':
  	    case 's':
  	      return n * s
  	    case 'milliseconds':
  	    case 'millisecond':
  	    case 'msecs':
  	    case 'msec':
  	    case 'ms':
  	      return n
  	    default:
  	      return undefined
  	  }
  	}
  
  	/**
  	 * Short format for `ms`.
  	 *
  	 * @param {Number} ms
  	 * @return {String}
  	 * @api private
  	 */
  
  	function fmtShort(ms) {
  	  if (ms >= d) {
  	    return Math.round(ms / d) + 'd'
  	  }
  	  if (ms >= h) {
  	    return Math.round(ms / h) + 'h'
  	  }
  	  if (ms >= m) {
  	    return Math.round(ms / m) + 'm'
  	  }
  	  if (ms >= s) {
  	    return Math.round(ms / s) + 's'
  	  }
  	  return ms + 'ms'
  	}
  
  	/**
  	 * Long format for `ms`.
  	 *
  	 * @param {Number} ms
  	 * @return {String}
  	 * @api private
  	 */
  
  	function fmtLong(ms) {
  	  return plural(ms, d, 'day') ||
  	    plural(ms, h, 'hour') ||
  	    plural(ms, m, 'minute') ||
  	    plural(ms, s, 'second') ||
  	    ms + ' ms'
  	}
  
  	/**
  	 * Pluralization helper.
  	 */
  
  	function plural(ms, n, name) {
  	  if (ms < n) {
  	    return
  	  }
  	  if (ms < n * 1.5) {
  	    return Math.floor(ms / n) + ' ' + name
  	  }
  	  return Math.ceil(ms / n) + ' ' + name + 's'
  	}
  
  
  /***/ },
  /* 8 */
  /***/ function(module, exports, __webpack_require__) {
  
  	
  	/**
  	 * Module dependencies.
  	 */
  
  	var debug = __webpack_require__(9)('socket.io-parser');
  	var json = __webpack_require__(12);
  	var Emitter = __webpack_require__(15);
  	var binary = __webpack_require__(16);
  	var isBuf = __webpack_require__(18);
  
  	/**
  	 * Protocol version.
  	 *
  	 * @api public
  	 */
  
  	exports.protocol = 4;
  
  	/**
  	 * Packet types.
  	 *
  	 * @api public
  	 */
  
  	exports.types = [
  	  'CONNECT',
  	  'DISCONNECT',
  	  'EVENT',
  	  'ACK',
  	  'ERROR',
  	  'BINARY_EVENT',
  	  'BINARY_ACK'
  	];
  
  	/**
  	 * Packet type `connect`.
  	 *
  	 * @api public
  	 */
  
  	exports.CONNECT = 0;
  
  	/**
  	 * Packet type `disconnect`.
  	 *
  	 * @api public
  	 */
  
  	exports.DISCONNECT = 1;
  
  	/**
  	 * Packet type `event`.
  	 *
  	 * @api public
  	 */
  
  	exports.EVENT = 2;
  
  	/**
  	 * Packet type `ack`.
  	 *
  	 * @api public
  	 */
  
  	exports.ACK = 3;
  
  	/**
  	 * Packet type `error`.
  	 *
  	 * @api public
  	 */
  
  	exports.ERROR = 4;
  
  	/**
  	 * Packet type 'binary event'
  	 *
  	 * @api public
  	 */
  
  	exports.BINARY_EVENT = 5;
  
  	/**
  	 * Packet type `binary ack`. For acks with binary arguments.
  	 *
  	 * @api public
  	 */
  
  	exports.BINARY_ACK = 6;
  
  	/**
  	 * Encoder constructor.
  	 *
  	 * @api public
  	 */
  
  	exports.Encoder = Encoder;
  
  	/**
  	 * Decoder constructor.
  	 *
  	 * @api public
  	 */
  
  	exports.Decoder = Decoder;
  
  	/**
  	 * A socket.io Encoder instance
  	 *
  	 * @api public
  	 */
  
  	function Encoder() {}
  
  	/**
  	 * Encode a packet as a single string if non-binary, or as a
  	 * buffer sequence, depending on packet type.
  	 *
  	 * @param {Object} obj - packet object
  	 * @param {Function} callback - function to handle encodings (likely engine.write)
  	 * @return Calls callback with Array of encodings
  	 * @api public
  	 */
  
  	Encoder.prototype.encode = function(obj, callback){
  	  debug('encoding packet %j', obj);
  
  	  if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) {
  	    encodeAsBinary(obj, callback);
  	  }
  	  else {
  	    var encoding = encodeAsString(obj);
  	    callback([encoding]);
  	  }
  	};
  
  	/**
  	 * Encode packet as string.
  	 *
  	 * @param {Object} packet
  	 * @return {String} encoded
  	 * @api private
  	 */
  
  	function encodeAsString(obj) {
  	  var str = '';
  	  var nsp = false;
  
  	  // first is type
  	  str += obj.type;
  
  	  // attachments if we have them
  	  if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) {
  	    str += obj.attachments;
  	    str += '-';
  	  }
  
  	  // if we have a namespace other than `/`
  	  // we append it followed by a comma `,`
  	  if (obj.nsp && '/' != obj.nsp) {
  	    nsp = true;
  	    str += obj.nsp;
  	  }
  
  	  // immediately followed by the id
  	  if (null != obj.id) {
  	    if (nsp) {
  	      str += ',';
  	      nsp = false;
  	    }
  	    str += obj.id;
  	  }
  
  	  // json data
  	  if (null != obj.data) {
  	    if (nsp) str += ',';
  	    str += json.stringify(obj.data);
  	  }
  
  	  debug('encoded %j as %s', obj, str);
  	  return str;
  	}
  
  	/**
  	 * Encode packet as 'buffer sequence' by removing blobs, and
  	 * deconstructing packet into object with placeholders and
  	 * a list of buffers.
  	 *
  	 * @param {Object} packet
  	 * @return {Buffer} encoded
  	 * @api private
  	 */
  
  	function encodeAsBinary(obj, callback) {
  
  	  function writeEncoding(bloblessData) {
  	    var deconstruction = binary.deconstructPacket(bloblessData);
  	    var pack = encodeAsString(deconstruction.packet);
  	    var buffers = deconstruction.buffers;
  
  	    buffers.unshift(pack); // add packet info to beginning of data list
  	    callback(buffers); // write all the buffers
  	  }
  
  	  binary.removeBlobs(obj, writeEncoding);
  	}
  
  	/**
  	 * A socket.io Decoder instance
  	 *
  	 * @return {Object} decoder
  	 * @api public
  	 */
  
  	function Decoder() {
  	  this.reconstructor = null;
  	}
  
  	/**
  	 * Mix in `Emitter` with Decoder.
  	 */
  
  	Emitter(Decoder.prototype);
  
  	/**
  	 * Decodes an ecoded packet string into packet JSON.
  	 *
  	 * @param {String} obj - encoded packet
  	 * @return {Object} packet
  	 * @api public
  	 */
  
  	Decoder.prototype.add = function(obj) {
  	  var packet;
  	  if ('string' == typeof obj) {
  	    packet = decodeString(obj);
  	    if (exports.BINARY_EVENT == packet.type || exports.BINARY_ACK == packet.type) { // binary packet's json
  	      this.reconstructor = new BinaryReconstructor(packet);
  
  	      // no attachments, labeled binary but no binary data to follow
  	      if (this.reconstructor.reconPack.attachments === 0) {
  	        this.emit('decoded', packet);
  	      }
  	    } else { // non-binary full packet
  	      this.emit('decoded', packet);
  	    }
  	  }
  	  else if (isBuf(obj) || obj.base64) { // raw binary data
  	    if (!this.reconstructor) {
  	      throw new Error('got binary data when not reconstructing a packet');
  	    } else {
  	      packet = this.reconstructor.takeBinaryData(obj);
  	      if (packet) { // received final buffer
  	        this.reconstructor = null;
  	        this.emit('decoded', packet);
  	      }
  	    }
  	  }
  	  else {
  	    throw new Error('Unknown type: ' + obj);
  	  }
  	};
  
  	/**
  	 * Decode a packet String (JSON data)
  	 *
  	 * @param {String} str
  	 * @return {Object} packet
  	 * @api private
  	 */
  
  	function decodeString(str) {
  	  var p = {};
  	  var i = 0;
  
  	  // look up type
  	  p.type = Number(str.charAt(0));
  	  if (null == exports.types[p.type]) return error();
  
  	  // look up attachments if type binary
  	  if (exports.BINARY_EVENT == p.type || exports.BINARY_ACK == p.type) {
  	    var buf = '';
  	    while (str.charAt(++i) != '-') {
  	      buf += str.charAt(i);
  	      if (i == str.length) break;
  	    }
  	    if (buf != Number(buf) || str.charAt(i) != '-') {
  	      throw new Error('Illegal attachments');
  	    }
  	    p.attachments = Number(buf);
  	  }
  
  	  // look up namespace (if any)
  	  if ('/' == str.charAt(i + 1)) {
  	    p.nsp = '';
  	    while (++i) {
  	      var c = str.charAt(i);
  	      if (',' == c) break;
  	      p.nsp += c;
  	      if (i == str.length) break;
  	    }
  	  } else {
  	    p.nsp = '/';
  	  }
  
  	  // look up id
  	  var next = str.charAt(i + 1);
  	  if ('' !== next && Number(next) == next) {
  	    p.id = '';
  	    while (++i) {
  	      var c = str.charAt(i);
  	      if (null == c || Number(c) != c) {
  	        --i;
  	        break;
  	      }
  	      p.id += str.charAt(i);
  	      if (i == str.length) break;
  	    }
  	    p.id = Number(p.id);
  	  }
  
  	  // look up json data
  	  if (str.charAt(++i)) {
  	    p = tryParse(p, str.substr(i));
  	  }
  
  	  debug('decoded %s as %j', str, p);
  	  return p;
  	}
  
  	function tryParse(p, str) {
  	  try {
  	    p.data = json.parse(str);
  	  } catch(e){
  	    return error();
  	  }
  	  return p; 
  	};
  
  	/**
  	 * Deallocates a parser's resources
  	 *
  	 * @api public
  	 */
  
  	Decoder.prototype.destroy = function() {
  	  if (this.reconstructor) {
  	    this.reconstructor.finishedReconstruction();
  	  }
  	};
  
  	/**
  	 * A manager of a binary event's 'buffer sequence'. Should
  	 * be constructed whenever a packet of type BINARY_EVENT is
  	 * decoded.
  	 *
  	 * @param {Object} packet
  	 * @return {BinaryReconstructor} initialized reconstructor
  	 * @api private
  	 */
  
  	function BinaryReconstructor(packet) {
  	  this.reconPack = packet;
  	  this.buffers = [];
  	}
  
  	/**
  	 * Method to be called when binary data received from connection
  	 * after a BINARY_EVENT packet.
  	 *
  	 * @param {Buffer | ArrayBuffer} binData - the raw binary data received
  	 * @return {null | Object} returns null if more binary data is expected or
  	 *   a reconstructed packet object if all buffers have been received.
  	 * @api private
  	 */
  
  	BinaryReconstructor.prototype.takeBinaryData = function(binData) {
  	  this.buffers.push(binData);
  	  if (this.buffers.length == this.reconPack.attachments) { // done with buffer list
  	    var packet = binary.reconstructPacket(this.reconPack, this.buffers);
  	    this.finishedReconstruction();
  	    return packet;
  	  }
  	  return null;
  	};
  
  	/**
  	 * Cleans up binary packet reconstruction variables.
  	 *
  	 * @api private
  	 */
  
  	BinaryReconstructor.prototype.finishedReconstruction = function() {
  	  this.reconPack = null;
  	  this.buffers = [];
  	};
  
  	function error(data){
  	  return {
  	    type: exports.ERROR,
  	    data: 'parser error'
  	  };
  	}
  
  
  /***/ },
  /* 9 */
  /***/ function(module, exports, __webpack_require__) {
  
  	
  	/**
  	 * This is the web browser implementation of `debug()`.
  	 *
  	 * Expose `debug()` as the module.
  	 */
  
  	exports = module.exports = __webpack_require__(10);
  	exports.log = log;
  	exports.formatArgs = formatArgs;
  	exports.save = save;
  	exports.load = load;
  	exports.useColors = useColors;
  	exports.storage = 'undefined' != typeof chrome
  	               && 'undefined' != typeof chrome.storage
  	                  ? chrome.storage.local
  	                  : localstorage();
  
  	/**
  	 * Colors.
  	 */
  
  	exports.colors = [
  	  'lightseagreen',
  	  'forestgreen',
  	  'goldenrod',
  	  'dodgerblue',
  	  'darkorchid',
  	  'crimson'
  	];
  
  	/**
  	 * Currently only WebKit-based Web Inspectors, Firefox >= v31,
  	 * and the Firebug extension (any Firefox version) are known
  	 * to support "%c" CSS customizations.
  	 *
  	 * TODO: add a `localStorage` variable to explicitly enable/disable colors
  	 */
  
  	function useColors() {
  	  // is webkit? http://stackoverflow.com/a/16459606/376773
  	  return ('WebkitAppearance' in document.documentElement.style) ||
  	    // is firebug? http://stackoverflow.com/a/398120/376773
  	    (window.console && (console.firebug || (console.exception && console.table))) ||
  	    // is firefox >= v31?
  	    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
  	    (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
  	}
  
  	/**
  	 * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
  	 */
  
  	exports.formatters.j = function(v) {
  	  return JSON.stringify(v);
  	};
  
  
  	/**
  	 * Colorize log arguments if enabled.
  	 *
  	 * @api public
  	 */
  
  	function formatArgs() {
  	  var args = arguments;
  	  var useColors = this.useColors;
  
  	  args[0] = (useColors ? '%c' : '')
  	    + this.namespace
  	    + (useColors ? ' %c' : ' ')
  	    + args[0]
  	    + (useColors ? '%c ' : ' ')
  	    + '+' + exports.humanize(this.diff);
  
  	  if (!useColors) return args;
  
  	  var c = 'color: ' + this.color;
  	  args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
  
  	  // the final "%c" is somewhat tricky, because there could be other
  	  // arguments passed either before or after the %c, so we need to
  	  // figure out the correct index to insert the CSS into
  	  var index = 0;
  	  var lastC = 0;
  	  args[0].replace(/%[a-z%]/g, function(match) {
  	    if ('%%' === match) return;
  	    index++;
  	    if ('%c' === match) {
  	      // we only are interested in the *last* %c
  	      // (the user may have provided their own)
  	      lastC = index;
  	    }
  	  });
  
  	  args.splice(lastC, 0, c);
  	  return args;
  	}
  
  	/**
  	 * Invokes `console.log()` when available.
  	 * No-op when `console.log` is not a "function".
  	 *
  	 * @api public
  	 */
  
  	function log() {
  	  // this hackery is required for IE8/9, where
  	  // the `console.log` function doesn't have 'apply'
  	  return 'object' === typeof console
  	    && console.log
  	    && Function.prototype.apply.call(console.log, console, arguments);
  	}
  
  	/**
  	 * Save `namespaces`.
  	 *
  	 * @param {String} namespaces
  	 * @api private
  	 */
  
  	function save(namespaces) {
  	  try {
  	    if (null == namespaces) {
  	      exports.storage.removeItem('debug');
  	    } else {
  	      exports.storage.debug = namespaces;
  	    }
  	  } catch(e) {}
  	}
  
  	/**
  	 * Load `namespaces`.
  	 *
  	 * @return {String} returns the previously persisted debug modes
  	 * @api private
  	 */
  
  	function load() {
  	  var r;
  	  try {
  	    r = exports.storage.debug;
  	  } catch(e) {}
  	  return r;
  	}
  
  	/**
  	 * Enable namespaces listed in `localStorage.debug` initially.
  	 */
  
  	exports.enable(load());
  
  	/**
  	 * Localstorage attempts to return the localstorage.
  	 *
  	 * This is necessary because safari throws
  	 * when a user disables cookies/localstorage
  	 * and you attempt to access it.
  	 *
  	 * @return {LocalStorage}
  	 * @api private
  	 */
  
  	function localstorage(){
  	  try {
  	    return window.localStorage;
  	  } catch (e) {}
  	}
  
  
  /***/ },
  /* 10 */
  /***/ function(module, exports, __webpack_require__) {
  
  	
  	/**
  	 * This is the common logic for both the Node.js and web browser
  	 * implementations of `debug()`.
  	 *
  	 * Expose `debug()` as the module.
  	 */
  
  	exports = module.exports = debug;
  	exports.coerce = coerce;
  	exports.disable = disable;
  	exports.enable = enable;
  	exports.enabled = enabled;
  	exports.humanize = __webpack_require__(11);
  
  	/**
  	 * The currently active debug mode names, and names to skip.
  	 */
  
  	exports.names = [];
  	exports.skips = [];
  
  	/**
  	 * Map of special "%n" handling functions, for the debug "format" argument.
  	 *
  	 * Valid key names are a single, lowercased letter, i.e. "n".
  	 */
  
  	exports.formatters = {};
  
  	/**
  	 * Previously assigned color.
  	 */
  
  	var prevColor = 0;
  
  	/**
  	 * Previous log timestamp.
  	 */
  
  	var prevTime;
  
  	/**
  	 * Select a color.
  	 *
  	 * @return {Number}
  	 * @api private
  	 */
  
  	function selectColor() {
  	  return exports.colors[prevColor++ % exports.colors.length];
  	}
  
  	/**
  	 * Create a debugger with the given `namespace`.
  	 *
  	 * @param {String} namespace
  	 * @return {Function}
  	 * @api public
  	 */
  
  	function debug(namespace) {
  
  	  // define the `disabled` version
  	  function disabled() {
  	  }
  	  disabled.enabled = false;
  
  	  // define the `enabled` version
  	  function enabled() {
  
  	    var self = enabled;
  
  	    // set `diff` timestamp
  	    var curr = +new Date();
  	    var ms = curr - (prevTime || curr);
  	    self.diff = ms;
  	    self.prev = prevTime;
  	    self.curr = curr;
  	    prevTime = curr;
  
  	    // add the `color` if not set
  	    if (null == self.useColors) self.useColors = exports.useColors();
  	    if (null == self.color && self.useColors) self.color = selectColor();
  
  	    var args = Array.prototype.slice.call(arguments);
  
  	    args[0] = exports.coerce(args[0]);
  
  	    if ('string' !== typeof args[0]) {
  	      // anything else let's inspect with %o
  	      args = ['%o'].concat(args);
  	    }
  
  	    // apply any `formatters` transformations
  	    var index = 0;
  	    args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
  	      // if we encounter an escaped % then don't increase the array index
  	      if (match === '%%') return match;
  	      index++;
  	      var formatter = exports.formatters[format];
  	      if ('function' === typeof formatter) {
  	        var val = args[index];
  	        match = formatter.call(self, val);
  
  	        // now we need to remove `args[index]` since it's inlined in the `format`
  	        args.splice(index, 1);
  	        index--;
  	      }
  	      return match;
  	    });
  
  	    if ('function' === typeof exports.formatArgs) {
  	      args = exports.formatArgs.apply(self, args);
  	    }
  	    var logFn = enabled.log || exports.log || console.log.bind(console);
  	    logFn.apply(self, args);
  	  }
  	  enabled.enabled = true;
  
  	  var fn = exports.enabled(namespace) ? enabled : disabled;
  
  	  fn.namespace = namespace;
  
  	  return fn;
  	}
  
  	/**
  	 * Enables a debug mode by namespaces. This can include modes
  	 * separated by a colon and wildcards.
  	 *
  	 * @param {String} namespaces
  	 * @api public
  	 */
  
  	function enable(namespaces) {
  	  exports.save(namespaces);
  
  	  var split = (namespaces || '').split(/[\s,]+/);
  	  var len = split.length;
  
  	  for (var i = 0; i < len; i++) {
  	    if (!split[i]) continue; // ignore empty strings
  	    namespaces = split[i].replace(/\*/g, '.*?');
  	    if (namespaces[0] === '-') {
  	      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
  	    } else {
  	      exports.names.push(new RegExp('^' + namespaces + '$'));
  	    }
  	  }
  	}
  
  	/**
  	 * Disable debug output.
  	 *
  	 * @api public
  	 */
  
  	function disable() {
  	  exports.enable('');
  	}
  
  	/**
  	 * Returns true if the given mode name is enabled, false otherwise.
  	 *
  	 * @param {String} name
  	 * @return {Boolean}
  	 * @api public
  	 */
  
  	function enabled(name) {
  	  var i, len;
  	  for (i = 0, len = exports.skips.length; i < len; i++) {
  	    if (exports.skips[i].test(name)) {
  	      return false;
  	    }
  	  }
  	  for (i = 0, len = exports.names.length; i < len; i++) {
  	    if (exports.names[i].test(name)) {
  	      return true;
  	    }
  	  }
  	  return false;
  	}
  
  	/**
  	 * Coerce `val`.
  	 *
  	 * @param {Mixed} val
  	 * @return {Mixed}
  	 * @api private
  	 */
  
  	function coerce(val) {
  	  if (val instanceof Error) return val.stack || val.message;
  	  return val;
  	}
  
  
  /***/ },
  /* 11 */
  /***/ function(module, exports) {
  
  	/**
  	 * Helpers.
  	 */
  
  	var s = 1000;
  	var m = s * 60;
  	var h = m * 60;
  	var d = h * 24;
  	var y = d * 365.25;
  
  	/**
  	 * Parse or format the given `val`.
  	 *
  	 * Options:
  	 *
  	 *  - `long` verbose formatting [false]
  	 *
  	 * @param {String|Number} val
  	 * @param {Object} options
  	 * @return {String|Number}
  	 * @api public
  	 */
  
  	module.exports = function(val, options){
  	  options = options || {};
  	  if ('string' == typeof val) return parse(val);
  	  return options.long
  	    ? long(val)
  	    : short(val);
  	};
  
  	/**
  	 * Parse the given `str` and return milliseconds.
  	 *
  	 * @param {String} str
  	 * @return {Number}
  	 * @api private
  	 */
  
  	function parse(str) {
  	  str = '' + str;
  	  if (str.length > 10000) return;
  	  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);
  	  if (!match) return;
  	  var n = parseFloat(match[1]);
  	  var type = (match[2] || 'ms').toLowerCase();
  	  switch (type) {
  	    case 'years':
  	    case 'year':
  	    case 'yrs':
  	    case 'yr':
  	    case 'y':
  	      return n * y;
  	    case 'days':
  	    case 'day':
  	    case 'd':
  	      return n * d;
  	    case 'hours':
  	    case 'hour':
  	    case 'hrs':
  	    case 'hr':
  	    case 'h':
  	      return n * h;
  	    case 'minutes':
  	    case 'minute':
  	    case 'mins':
  	    case 'min':
  	    case 'm':
  	      return n * m;
  	    case 'seconds':
  	    case 'second':
  	    case 'secs':
  	    case 'sec':
  	    case 's':
  	      return n * s;
  	    case 'milliseconds':
  	    case 'millisecond':
  	    case 'msecs':
  	    case 'msec':
  	    case 'ms':
  	      return n;
  	  }
  	}
  
  	/**
  	 * Short format for `ms`.
  	 *
  	 * @param {Number} ms
  	 * @return {String}
  	 * @api private
  	 */
  
  	function short(ms) {
  	  if (ms >= d) return Math.round(ms / d) + 'd';
  	  if (ms >= h) return Math.round(ms / h) + 'h';
  	  if (ms >= m) return Math.round(ms / m) + 'm';
  	  if (ms >= s) return Math.round(ms / s) + 's';
  	  return ms + 'ms';
  	}
  
  	/**
  	 * Long format for `ms`.
  	 *
  	 * @param {Number} ms
  	 * @return {String}
  	 * @api private
  	 */
  
  	function long(ms) {
  	  return plural(ms, d, 'day')
  	    || plural(ms, h, 'hour')
  	    || plural(ms, m, 'minute')
  	    || plural(ms, s, 'second')
  	    || ms + ' ms';
  	}
  
  	/**
  	 * Pluralization helper.
  	 */
  
  	function plural(ms, n, name) {
  	  if (ms < n) return;
  	  if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
  	  return Math.ceil(ms / n) + ' ' + name + 's';
  	}
  
  
  /***/ },
  /* 12 */
  /***/ function(module, exports, __webpack_require__) {
  
  	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! JSON v3.3.2 | http://bestiejs.github.io/json3 | Copyright 2012-2014, Kit Cambridge | http://kit.mit-license.org */
  	;(function () {
  	  // Detect the `define` function exposed by asynchronous module loaders. The
  	  // strict `define` check is necessary for compatibility with `r.js`.
  	  var isLoader = "function" === "function" && __webpack_require__(14);
  
  	  // A set of types used to distinguish objects from primitives.
  	  var objectTypes = {
  	    "function": true,
  	    "object": true
  	  };
  
  	  // Detect the `exports` object exposed by CommonJS implementations.
  	  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
  
  	  // Use the `global` object exposed by Node (including Browserify via
  	  // `insert-module-globals`), Narwhal, and Ringo as the default context,
  	  // and the `window` object in browsers. Rhino exports a `global` function
  	  // instead.
  	  var root = objectTypes[typeof window] && window || this,
  	      freeGlobal = freeExports && objectTypes[typeof module] && module && !module.nodeType && typeof global == "object" && global;
  
  	  if (freeGlobal && (freeGlobal["global"] === freeGlobal || freeGlobal["window"] === freeGlobal || freeGlobal["self"] === freeGlobal)) {
  	    root = freeGlobal;
  	  }
  
  	  // Public: Initializes JSON 3 using the given `context` object, attaching the
  	  // `stringify` and `parse` functions to the specified `exports` object.
  	  function runInContext(context, exports) {
  	    context || (context = root["Object"]());
  	    exports || (exports = root["Object"]());
  
  	    // Native constructor aliases.
  	    var Number = context["Number"] || root["Number"],
  	        String = context["String"] || root["String"],
  	        Object = context["Object"] || root["Object"],
  	        Date = context["Date"] || root["Date"],
  	        SyntaxError = context["SyntaxError"] || root["SyntaxError"],
  	        TypeError = context["TypeError"] || root["TypeError"],
  	        Math = context["Math"] || root["Math"],
  	        nativeJSON = context["JSON"] || root["JSON"];
  
  	    // Delegate to the native `stringify` and `parse` implementations.
  	    if (typeof nativeJSON == "object" && nativeJSON) {
  	      exports.stringify = nativeJSON.stringify;
  	      exports.parse = nativeJSON.parse;
  	    }
  
  	    // Convenience aliases.
  	    var objectProto = Object.prototype,
  	        getClass = objectProto.toString,
  	        isProperty, forEach, undef;
  
  	    // Test the `Date#getUTC*` methods. Based on work by @Yaffle.
  	    var isExtended = new Date(-3509827334573292);
  	    try {
  	      // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical
  	      // results for certain dates in Opera >= 10.53.
  	      isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 &&
  	        // Safari < 2.0.2 stores the internal millisecond time value correctly,
  	        // but clips the values returned by the date methods to the range of
  	        // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]).
  	        isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708;
  	    } catch (exception) {}
  
  	    // Internal: Determines whether the native `JSON.stringify` and `parse`
  	    // implementations are spec-compliant. Based on work by Ken Snyder.
  	    function has(name) {
  	      if (has[name] !== undef) {
  	        // Return cached feature test result.
  	        return has[name];
  	      }
  	      var isSupported;
  	      if (name == "bug-string-char-index") {
  	        // IE <= 7 doesn't support accessing string characters using square
  	        // bracket notation. IE 8 only supports this for primitives.
  	        isSupported = "a"[0] != "a";
  	      } else if (name == "json") {
  	        // Indicates whether both `JSON.stringify` and `JSON.parse` are
  	        // supported.
  	        isSupported = has("json-stringify") && has("json-parse");
  	      } else {
  	        var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';
  	        // Test `JSON.stringify`.
  	        if (name == "json-stringify") {
  	          var stringify = exports.stringify, stringifySupported = typeof stringify == "function" && isExtended;
  	          if (stringifySupported) {
  	            // A test function object with a custom `toJSON` method.
  	            (value = function () {
  	              return 1;
  	            }).toJSON = value;
  	            try {
  	              stringifySupported =
  	                // Firefox 3.1b1 and b2 serialize string, number, and boolean
  	                // primitives as object literals.
  	                stringify(0) === "0" &&
  	                // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object
  	                // literals.
  	                stringify(new Number()) === "0" &&
  	                stringify(new String()) == '""' &&
  	                // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or
  	                // does not define a canonical JSON representation (this applies to
  	                // objects with `toJSON` properties as well, *unless* they are nested
  	                // within an object or array).
  	                stringify(getClass) === undef &&
  	                // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and
  	                // FF 3.1b3 pass this test.
  	                stringify(undef) === undef &&
  	                // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s,
  	                // respectively, if the value is omitted entirely.
  	                stringify() === undef &&
  	                // FF 3.1b1, 2 throw an error if the given value is not a number,
  	                // string, array, object, Boolean, or `null` literal. This applies to
  	                // objects with custom `toJSON` methods as well, unless they are nested
  	                // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON`
  	                // methods entirely.
  	                stringify(value) === "1" &&
  	                stringify([value]) == "[1]" &&
  	                // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of
  	                // `"[null]"`.
  	                stringify([undef]) == "[null]" &&
  	                // YUI 3.0.0b1 fails to serialize `null` literals.
  	                stringify(null) == "null" &&
  	                // FF 3.1b1, 2 halts serialization if an array contains a function:
  	                // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3
  	                // elides non-JSON values from objects and arrays, unless they
  	                // define custom `toJSON` methods.
  	                stringify([undef, getClass, null]) == "[null,null,null]" &&
  	                // Simple serialization test. FF 3.1b1 uses Unicode escape sequences
  	                // where character escape codes are expected (e.g., `\b` => `\u0008`).
  	                stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized &&
  	                // FF 3.1b1 and b2 ignore the `filter` and `width` arguments.
  	                stringify(null, value) === "1" &&
  	                stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" &&
  	                // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly
  	                // serialize extended years.
  	                stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' &&
  	                // The milliseconds are optional in ES 5, but required in 5.1.
  	                stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' &&
  	                // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative
  	                // four-digit years instead of six-digit years. Credits: @Yaffle.
  	                stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' &&
  	                // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond
  	                // values less than 1000. Credits: @Yaffle.
  	                stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"';
  	            } catch (exception) {
  	              stringifySupported = false;
  	            }
  	          }
  	          isSupported = stringifySupported;
  	        }
  	        // Test `JSON.parse`.
  	        if (name == "json-parse") {
  	          var parse = exports.parse;
  	          if (typeof parse == "function") {
  	            try {
  	              // FF 3.1b1, b2 will throw an exception if a bare literal is provided.
  	              // Conforming implementations should also coerce the initial argument to
  	              // a string prior to parsing.
  	              if (parse("0") === 0 && !parse(false)) {
  	                // Simple parsing test.
  	                value = parse(serialized);
  	                var parseSupported = value["a"].length == 5 && value["a"][0] === 1;
  	                if (parseSupported) {
  	                  try {
  	                    // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings.
  	                    parseSupported = !parse('"\t"');
  	                  } catch (exception) {}
  	                  if (parseSupported) {
  	                    try {
  	                      // FF 4.0 and 4.0.1 allow leading `+` signs and leading
  	                      // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow
  	                      // certain octal literals.
  	                      parseSupported = parse("01") !== 1;
  	                    } catch (exception) {}
  	                  }
  	                  if (parseSupported) {
  	                    try {
  	                      // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal
  	                      // points. These environments, along with FF 3.1b1 and 2,
  	                      // also allow trailing commas in JSON objects and arrays.
  	                      parseSupported = parse("1.") !== 1;
  	                    } catch (exception) {}
  	                  }
  	                }
  	              }
  	            } catch (exception) {
  	              parseSupported = false;
  	            }
  	          }
  	          isSupported = parseSupported;
  	        }
  	      }
  	      return has[name] = !!isSupported;
  	    }
  
  	    if (!has("json")) {
  	      // Common `[[Class]]` name aliases.
  	      var functionClass = "[object Function]",
  	          dateClass = "[object Date]",
  	          numberClass = "[object Number]",
  	          stringClass = "[object String]",
  	          arrayClass = "[object Array]",
  	          booleanClass = "[object Boolean]";
  
  	      // Detect incomplete support for accessing string characters by index.
  	      var charIndexBuggy = has("bug-string-char-index");
  
  	      // Define additional utility methods if the `Date` methods are buggy.
  	      if (!isExtended) {
  	        var floor = Math.floor;
  	        // A mapping between the months of the year and the number of days between
  	        // January 1st and the first of the respective month.
  	        var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
  	        // Internal: Calculates the number of days between the Unix epoch and the
  	        // first day of the given month.
  	        var getDay = function (year, month) {
  	          return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);
  	        };
  	      }
  
  	      // Internal: Determines if a property is a direct property of the given
  	      // object. Delegates to the native `Object#hasOwnProperty` method.
  	      if (!(isProperty = objectProto.hasOwnProperty)) {
  	        isProperty = function (property) {
  	          var members = {}, constructor;
  	          if ((members.__proto__ = null, members.__proto__ = {
  	            // The *proto* property cannot be set multiple times in recent
  	            // versions of Firefox and SeaMonkey.
  	            "toString": 1
  	          }, members).toString != getClass) {
  	            // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but
  	            // supports the mutable *proto* property.
  	            isProperty = function (property) {
  	              // Capture and break the object's prototype chain (see section 8.6.2
  	              // of the ES 5.1 spec). The parenthesized expression prevents an
  	              // unsafe transformation by the Closure Compiler.
  	              var original = this.__proto__, result = property in (this.__proto__ = null, this);
  	              // Restore the original prototype chain.
  	              this.__proto__ = original;
  	              return result;
  	            };
  	          } else {
  	            // Capture a reference to the top-level `Object` constructor.
  	            constructor = members.constructor;
  	            // Use the `constructor` property to simulate `Object#hasOwnProperty` in
  	            // other environments.
  	            isProperty = function (property) {
  	              var parent = (this.constructor || constructor).prototype;
  	              return property in this && !(property in parent && this[property] === parent[property]);
  	            };
  	          }
  	          members = null;
  	          return isProperty.call(this, property);
  	        };
  	      }
  
  	      // Internal: Normalizes the `for...in` iteration algorithm across
  	      // environments. Each enumerated key is yielded to a `callback` function.
  	      forEach = function (object, callback) {
  	        var size = 0, Properties, members, property;
  
  	        // Tests for bugs in the current environment's `for...in` algorithm. The
  	        // `valueOf` property inherits the non-enumerable flag from
  	        // `Object.prototype` in older versions of IE, Netscape, and Mozilla.
  	        (Properties = function () {
  	          this.valueOf = 0;
  	        }).prototype.valueOf = 0;
  
  	        // Iterate over a new instance of the `Properties` class.
  	        members = new Properties();
  	        for (property in members) {
  	          // Ignore all properties inherited from `Object.prototype`.
  	          if (isProperty.call(members, property)) {
  	            size++;
  	          }
  	        }
  	        Properties = members = null;
  
  	        // Normalize the iteration algorithm.
  	        if (!size) {
  	          // A list of non-enumerable properties inherited from `Object.prototype`.
  	          members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"];
  	          // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable
  	          // properties.
  	          forEach = function (object, callback) {
  	            var isFunction = getClass.call(object) == functionClass, property, length;
  	            var hasProperty = !isFunction && typeof object.constructor != "function" && objectTypes[typeof object.hasOwnProperty] && object.hasOwnProperty || isProperty;
  	            for (property in object) {
  	              // Gecko <= 1.0 enumerates the `prototype` property of functions under
  	              // certain conditions; IE does not.
  	              if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) {
  	                callback(property);
  	              }
  	            }
  	            // Manually invoke the callback for each non-enumerable property.
  	            for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property));
  	          };
  	        } else if (size == 2) {
  	          // Safari <= 2.0.4 enumerates shadowed properties twice.
  	          forEach = function (object, callback) {
  	            // Create a set of iterated properties.
  	            var members = {}, isFunction = getClass.call(object) == functionClass, property;
  	            for (property in object) {
  	              // Store each property name to prevent double enumeration. The
  	              // `prototype` property of functions is not enumerated due to cross-
  	              // environment inconsistencies.
  	              if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) {
  	                callback(property);
  	              }
  	            }
  	          };
  	        } else {
  	          // No bugs detected; use the standard `for...in` algorithm.
  	          forEach = function (object, callback) {
  	            var isFunction = getClass.call(object) == functionClass, property, isConstructor;
  	            for (property in object) {
  	              if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) {
  	                callback(property);
  	              }
  	            }
  	            // Manually invoke the callback for the `constructor` property due to
  	            // cross-environment inconsistencies.
  	            if (isConstructor || isProperty.call(object, (property = "constructor"))) {
  	              callback(property);
  	            }
  	          };
  	        }
  	        return forEach(object, callback);
  	      };
  
  	      // Public: Serializes a JavaScript `value` as a JSON string. The optional
  	      // `filter` argument may specify either a function that alters how object and
  	      // array members are serialized, or an array of strings and numbers that
  	      // indicates which properties should be serialized. The optional `width`
  	      // argument may be either a string or number that specifies the indentation
  	      // level of the output.
  	      if (!has("json-stringify")) {
  	        // Internal: A map of control characters and their escaped equivalents.
  	        var Escapes = {
  	          92: "\\\\",
  	          34: '\\"',
  	          8: "\\b",
  	          12: "\\f",
  	          10: "\\n",
  	          13: "\\r",
  	          9: "\\t"
  	        };
  
  	        // Internal: Converts `value` into a zero-padded string such that its
  	        // length is at least equal to `width`. The `width` must be <= 6.
  	        var leadingZeroes = "000000";
  	        var toPaddedString = function (width, value) {
  	          // The `|| 0` expression is necessary to work around a bug in
  	          // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`.
  	          return (leadingZeroes + (value || 0)).slice(-width);
  	        };
  
  	        // Internal: Double-quotes a string `value`, replacing all ASCII control
  	        // characters (characters with code unit values between 0 and 31) with
  	        // their escaped equivalents. This is an implementation of the
  	        // `Quote(value)` operation defined in ES 5.1 section 15.12.3.
  	        var unicodePrefix = "\\u00";
  	        var quote = function (value) {
  	          var result = '"', index = 0, length = value.length, useCharIndex = !charIndexBuggy || length > 10;
  	          var symbols = useCharIndex && (charIndexBuggy ? value.split("") : value);
  	          for (; index < length; index++) {
  	            var charCode = value.charCodeAt(index);
  	            // If the character is a control character, append its Unicode or
  	            // shorthand escape sequence; otherwise, append the character as-is.
  	            switch (charCode) {
  	              case 8: case 9: case 10: case 12: case 13: case 34: case 92:
  	                result += Escapes[charCode];
  	                break;
  	              default:
  	                if (charCode < 32) {
  	                  result += unicodePrefix + toPaddedString(2, charCode.toString(16));
  	                  break;
  	                }
  	                result += useCharIndex ? symbols[index] : value.charAt(index);
  	            }
  	          }
  	          return result + '"';
  	        };
  
  	        // Internal: Recursively serializes an object. Implements the
  	        // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.
  	        var serialize = function (property, object, callback, properties, whitespace, indentation, stack) {
  	          var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result;
  	          try {
  	            // Necessary for host object support.
  	            value = object[property];
  	          } catch (exception) {}
  	          if (typeof value == "object" && value) {
  	            className = getClass.call(value);
  	            if (className == dateClass && !isProperty.call(value, "toJSON")) {
  	              if (value > -1 / 0 && value < 1 / 0) {
  	                // Dates are serialized according to the `Date#toJSON` method
  	                // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15
  	                // for the ISO 8601 date time string format.
  	                if (getDay) {
  	                  // Manually compute the year, month, date, hours, minutes,
  	                  // seconds, and milliseconds if the `getUTC*` methods are
  	                  // buggy. Adapted from @Yaffle's `date-shim` project.
  	                  date = floor(value / 864e5);
  	                  for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++);
  	                  for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++);
  	                  date = 1 + date - getDay(year, month);
  	                  // The `time` value specifies the time within the day (see ES
  	                  // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used
  	                  // to compute `A modulo B`, as the `%` operator does not
  	                  // correspond to the `modulo` operation for negative numbers.
  	                  time = (value % 864e5 + 864e5) % 864e5;
  	                  // The hours, minutes, seconds, and milliseconds are obtained by
  	                  // decomposing the time within the day. See section 15.9.1.10.
  	                  hours = floor(time / 36e5) % 24;
  	                  minutes = floor(time / 6e4) % 60;
  	                  seconds = floor(time / 1e3) % 60;
  	                  milliseconds = time % 1e3;
  	                } else {
  	                  year = value.getUTCFullYear();
  	                  month = value.getUTCMonth();
  	                  date = value.getUTCDate();
  	                  hours = value.getUTCHours();
  	                  minutes = value.getUTCMinutes();
  	                  seconds = value.getUTCSeconds();
  	                  milliseconds = value.getUTCMilliseconds();
  	                }
  	                // Serialize extended years correctly.
  	                value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +
  	                  "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) +
  	                  // Months, dates, hours, minutes, and seconds should have two
  	                  // digits; milliseconds should have three.
  	                  "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) +
  	                  // Milliseconds are optional in ES 5.0, but required in 5.1.
  	                  "." + toPaddedString(3, milliseconds) + "Z";
  	              } else {
  	                value = null;
  	              }
  	            } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) {
  	              // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the
  	              // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3
  	              // ignores all `toJSON` methods on these objects unless they are
  	              // defined directly on an instance.
  	              value = value.toJSON(property);
  	            }
  	          }
  	          if (callback) {
  	            // If a replacement function was provided, call it to obtain the value
  	            // for serialization.
  	            value = callback.call(object, property, value);
  	          }
  	          if (value === null) {
  	            return "null";
  	          }
  	          className = getClass.call(value);
  	          if (className == booleanClass) {
  	            // Booleans are represented literally.
  	            return "" + value;
  	          } else if (className == numberClass) {
  	            // JSON numbers must be finite. `Infinity` and `NaN` are serialized as
  	            // `"null"`.
  	            return value > -1 / 0 && value < 1 / 0 ? "" + value : "null";
  	          } else if (className == stringClass) {
  	            // Strings are double-quoted and escaped.
  	            return quote("" + value);
  	          }
  	          // Recursively serialize objects and arrays.
  	          if (typeof value == "object") {
  	            // Check for cyclic structures. This is a linear search; performance
  	            // is inversely proportional to the number of unique nested objects.
  	            for (length = stack.length; length--;) {
  	              if (stack[length] === value) {
  	                // Cyclic structures cannot be serialized by `JSON.stringify`.
  	                throw TypeError();
  	              }
  	            }
  	            // Add the object to the stack of traversed objects.
  	            stack.push(value);
  	            results = [];
  	            // Save the current indentation level and indent one additional level.
  	            prefix = indentation;
  	            indentation += whitespace;
  	            if (className == arrayClass) {
  	              // Recursively serialize array elements.
  	              for (index = 0, length = value.length; index < length; index++) {
  	                element = serialize(index, value, callback, properties, whitespace, indentation, stack);
  	                results.push(element === undef ? "null" : element);
  	              }
  	              result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]";
  	            } else {
  	              // Recursively serialize object members. Members are selected from
  	              // either a user-specified list of property names, or the object
  	              // itself.
  	              forEach(properties || value, function (property) {
  	                var element = serialize(property, value, callback, properties, whitespace, indentation, stack);
  	                if (element !== undef) {
  	                  // According to ES 5.1 section 15.12.3: "If `gap` {whitespace}
  	                  // is not the empty string, let `member` {quote(property) + ":"}
  	                  // be the concatenation of `member` and the `space` character."
  	                  // The "`space` character" refers to the literal space
  	                  // character, not the `space` {width} argument provided to
  	                  // `JSON.stringify`.
  	                  results.push(quote(property) + ":" + (whitespace ? " " : "") + element);
  	                }
  	              });
  	              result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}";
  	            }
  	            // Remove the object from the traversed object stack.
  	            stack.pop();
  	            return result;
  	          }
  	        };
  
  	        // Public: `JSON.stringify`. See ES 5.1 section 15.12.3.
  	        exports.stringify = function (source, filter, width) {
  	          var whitespace, callback, properties, className;
  	          if (objectTypes[typeof filter] && filter) {
  	            if ((className = getClass.call(filter)) == functionClass) {
  	              callback = filter;
  	            } else if (className == arrayClass) {
  	              // Convert the property names array into a makeshift set.
  	              properties = {};
  	              for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1));
  	            }
  	          }
  	          if (width) {
  	            if ((className = getClass.call(width)) == numberClass) {
  	              // Convert the `width` to an integer and create a string containing
  	              // `width` number of space characters.
  	              if ((width -= width % 1) > 0) {
  	                for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " ");
  	              }
  	            } else if (className == stringClass) {
  	              whitespace = width.length <= 10 ? width : width.slice(0, 10);
  	            }
  	          }
  	          // Opera <= 7.54u2 discards the values associated with empty string keys
  	          // (`""`) only if they are used directly within an object member list
  	          // (e.g., `!("" in { "": 1})`).
  	          return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []);
  	        };
  	      }
  
  	      // Public: Parses a JSON source string.
  	      if (!has("json-parse")) {
  	        var fromCharCode = String.fromCharCode;
  
  	        // Internal: A map of escaped control characters and their unescaped
  	        // equivalents.
  	        var Unescapes = {
  	          92: "\\",
  	          34: '"',
  	          47: "/",
  	          98: "\b",
  	          116: "\t",
  	          110: "\n",
  	          102: "\f",
  	          114: "\r"
  	        };
  
  	        // Internal: Stores the parser state.
  	        var Index, Source;
  
  	        // Internal: Resets the parser state and throws a `SyntaxError`.
  	        var abort = function () {
  	          Index = Source = null;
  	          throw SyntaxError();
  	        };
  
  	        // Internal: Returns the next token, or `"$"` if the parser has reached
  	        // the end of the source string. A token may be a string, number, `null`
  	        // literal, or Boolean literal.
  	        var lex = function () {
  	          var source = Source, length = source.length, value, begin, position, isSigned, charCode;
  	          while (Index < length) {
  	            charCode = source.charCodeAt(Index);
  	            switch (charCode) {
  	              case 9: case 10: case 13: case 32:
  	                // Skip whitespace tokens, including tabs, carriage returns, line
  	                // feeds, and space characters.
  	                Index++;
  	                break;
  	              case 123: case 125: case 91: case 93: case 58: case 44:
  	                // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at
  	                // the current position.
  	                value = charIndexBuggy ? source.charAt(Index) : source[Index];
  	                Index++;
  	                return value;
  	              case 34:
  	                // `"` delimits a JSON string; advance to the next character and
  	                // begin parsing the string. String tokens are prefixed with the
  	                // sentinel `@` character to distinguish them from punctuators and
  	                // end-of-string tokens.
  	                for (value = "@", Index++; Index < length;) {
  	                  charCode = source.charCodeAt(Index);
  	                  if (charCode < 32) {
  	                    // Unescaped ASCII control characters (those with a code unit
  	                    // less than the space character) are not permitted.
  	                    abort();
  	                  } else if (charCode == 92) {
  	                    // A reverse solidus (`\`) marks the beginning of an escaped
  	                    // control character (including `"`, `\`, and `/`) or Unicode
  	                    // escape sequence.
  	                    charCode = source.charCodeAt(++Index);
  	                    switch (charCode) {
  	                      case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114:
  	                        // Revive escaped control characters.
  	                        value += Unescapes[charCode];
  	                        Index++;
  	                        break;
  	                      case 117:
  	                        // `\u` marks the beginning of a Unicode escape sequence.
  	                        // Advance to the first character and validate the
  	                        // four-digit code point.
  	                        begin = ++Index;
  	                        for (position = Index + 4; Index < position; Index++) {
  	                          charCode = source.charCodeAt(Index);
  	                          // A valid sequence comprises four hexdigits (case-
  	                          // insensitive) that form a single hexadecimal value.
  	                          if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) {
  	                            // Invalid Unicode escape sequence.
  	                            abort();
  	                          }
  	                        }
  	                        // Revive the escaped character.
  	                        value += fromCharCode("0x" + source.slice(begin, Index));
  	                        break;
  	                      default:
  	                        // Invalid escape sequence.
  	                        abort();
  	                    }
  	                  } else {
  	                    if (charCode == 34) {
  	                      // An unescaped double-quote character marks the end of the
  	                      // string.
  	                      break;
  	                    }
  	                    charCode = source.charCodeAt(Index);
  	                    begin = Index;
  	                    // Optimize for the common case where a string is valid.
  	                    while (charCode >= 32 && charCode != 92 && charCode != 34) {
  	                      charCode = source.charCodeAt(++Index);
  	                    }
  	                    // Append the string as-is.
  	                    value += source.slice(begin, Index);
  	                  }
  	                }
  	                if (source.charCodeAt(Index) == 34) {
  	                  // Advance to the next character and return the revived string.
  	                  Index++;
  	                  return value;
  	                }
  	                // Unterminated string.
  	                abort();
  	              default:
  	                // Parse numbers and literals.
  	                begin = Index;
  	                // Advance past the negative sign, if one is specified.
  	                if (charCode == 45) {
  	                  isSigned = true;
  	                  charCode = source.charCodeAt(++Index);
  	                }
  	                // Parse an integer or floating-point value.
  	                if (charCode >= 48 && charCode <= 57) {
  	                  // Leading zeroes are interpreted as octal literals.
  	                  if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) {
  	                    // Illegal octal literal.
  	                    abort();
  	                  }
  	                  isSigned = false;
  	                  // Parse the integer component.
  	                  for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++);
  	                  // Floats cannot contain a leading decimal point; however, this
  	                  // case is already accounted for by the parser.
  	                  if (source.charCodeAt(Index) == 46) {
  	                    position = ++Index;
  	                    // Parse the decimal component.
  	                    for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
  	                    if (position == Index) {
  	                      // Illegal trailing decimal.
  	                      abort();
  	                    }
  	                    Index = position;
  	                  }
  	                  // Parse exponents. The `e` denoting the exponent is
  	                  // case-insensitive.
  	                  charCode = source.charCodeAt(Index);
  	                  if (charCode == 101 || charCode == 69) {
  	                    charCode = source.charCodeAt(++Index);
  	                    // Skip past the sign following the exponent, if one is
  	                    // specified.
  	                    if (charCode == 43 || charCode == 45) {
  	                      Index++;
  	                    }
  	                    // Parse the exponential component.
  	                    for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
  	                    if (position == Index) {
  	                      // Illegal empty exponent.
  	                      abort();
  	                    }
  	                    Index = position;
  	                  }
  	                  // Coerce the parsed value to a JavaScript number.
  	                  return +source.slice(begin, Index);
  	                }
  	                // A negative sign may only precede numbers.
  	                if (isSigned) {
  	                  abort();
  	                }
  	                // `true`, `false`, and `null` literals.
  	                if (source.slice(Index, Index + 4) == "true") {
  	                  Index += 4;
  	                  return true;
  	                } else if (source.slice(Index, Index + 5) == "false") {
  	                  Index += 5;
  	                  return false;
  	                } else if (source.slice(Index, Index + 4) == "null") {
  	                  Index += 4;
  	                  return null;
  	                }
  	                // Unrecognized token.
  	                abort();
  	            }
  	          }
  	          // Return the sentinel `$` character if the parser has reached the end
  	          // of the source string.
  	          return "$";
  	        };
  
  	        // Internal: Parses a JSON `value` token.
  	        var get = function (value) {
  	          var results, hasMembers;
  	          if (value == "$") {
  	            // Unexpected end of input.
  	            abort();
  	          }
  	          if (typeof value == "string") {
  	            if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") {
  	              // Remove the sentinel `@` character.
  	              return value.slice(1);
  	            }
  	            // Parse object and array literals.
  	            if (value == "[") {
  	              // Parses a JSON array, returning a new JavaScript array.
  	              results = [];
  	              for (;; hasMembers || (hasMembers = true)) {
  	                value = lex();
  	                // A closing square bracket marks the end of the array literal.
  	                if (value == "]") {
  	                  break;
  	                }
  	                // If the array literal contains elements, the current token
  	                // should be a comma separating the previous element from the
  	                // next.
  	                if (hasMembers) {
  	                  if (value == ",") {
  	                    value = lex();
  	                    if (value == "]") {
  	                      // Unexpected trailing `,` in array literal.
  	                      abort();
  	                    }
  	                  } else {
  	                    // A `,` must separate each array element.
  	                    abort();
  	                  }
  	                }
  	                // Elisions and leading commas are not permitted.
  	                if (value == ",") {
  	                  abort();
  	                }
  	                results.push(get(value));
  	              }
  	              return results;
  	            } else if (value == "{") {
  	              // Parses a JSON object, returning a new JavaScript object.
  	              results = {};
  	              for (;; hasMembers || (hasMembers = true)) {
  	                value = lex();
  	                // A closing curly brace marks the end of the object literal.
  	                if (value == "}") {
  	                  break;
  	                }
  	                // If the object literal contains members, the current token
  	                // should be a comma separator.
  	                if (hasMembers) {
  	                  if (value == ",") {
  	                    value = lex();
  	                    if (value == "}") {
  	                      // Unexpected trailing `,` in object literal.
  	                      abort();
  	                    }
  	                  } else {
  	                    // A `,` must separate each object member.
  	                    abort();
  	                  }
  	                }
  	                // Leading commas are not permitted, object property names must be
  	                // double-quoted strings, and a `:` must separate each property
  	                // name and value.
  	                if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") {
  	                  abort();
  	                }
  	                results[value.slice(1)] = get(lex());
  	              }
  	              return results;
  	            }
  	            // Unexpected token encountered.
  	            abort();
  	          }
  	          return value;
  	        };
  
  	        // Internal: Updates a traversed object member.
  	        var update = function (source, property, callback) {
  	          var element = walk(source, property, callback);
  	          if (element === undef) {
  	            delete source[property];
  	          } else {
  	            source[property] = element;
  	          }
  	        };
  
  	        // Internal: Recursively traverses a parsed JSON object, invoking the
  	        // `callback` function for each value. This is an implementation of the
  	        // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.
  	        var walk = function (source, property, callback) {
  	          var value = source[property], length;
  	          if (typeof value == "object" && value) {
  	            // `forEach` can't be used to traverse an array in Opera <= 8.54
  	            // because its `Object#hasOwnProperty` implementation returns `false`
  	            // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`).
  	            if (getClass.call(value) == arrayClass) {
  	              for (length = value.length; length--;) {
  	                update(value, length, callback);
  	              }
  	            } else {
  	              forEach(value, function (property) {
  	                update(value, property, callback);
  	              });
  	            }
  	          }
  	          return callback.call(source, property, value);
  	        };
  
  	        // Public: `JSON.parse`. See ES 5.1 section 15.12.2.
  	        exports.parse = function (source, callback) {
  	          var result, value;
  	          Index = 0;
  	          Source = "" + source;
  	          result = get(lex());
  	          // If a JSON string contains multiple tokens, it is invalid.
  	          if (lex() != "$") {
  	            abort();
  	          }
  	          // Reset the parser state.
  	          Index = Source = null;
  	          return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result;
  	        };
  	      }
  	    }
  
  	    exports["runInContext"] = runInContext;
  	    return exports;
  	  }
  
  	  if (freeExports && !isLoader) {
  	    // Export for CommonJS environments.
  	    runInContext(root, freeExports);
  	  } else {
  	    // Export for web browsers and JavaScript engines.
  	    var nativeJSON = root.JSON,
  	        previousJSON = root["JSON3"],
  	        isRestored = false;
  
  	    var JSON3 = runInContext(root, (root["JSON3"] = {
  	      // Public: Restores the original value of the global `JSON` object and
  	      // returns a reference to the `JSON3` object.
  	      "noConflict": function () {
  	        if (!isRestored) {
  	          isRestored = true;
  	          root.JSON = nativeJSON;
  	          root["JSON3"] = previousJSON;
  	          nativeJSON = previousJSON = null;
  	        }
  	        return JSON3;
  	      }
  	    }));
  
  	    root.JSON = {
  	      "parse": JSON3.parse,
  	      "stringify": JSON3.stringify
  	    };
  	  }
  
  	  // Export for asynchronous module loaders.
  	  if (isLoader) {
  	    !(__WEBPACK_AMD_DEFINE_RESULT__ = function () {
  	      return JSON3;
  	    }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  	  }
  	}).call(this);
  
  	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(13)(module), (function() { return this; }())))
  
  /***/ },
  /* 13 */
  /***/ function(module, exports) {
  
  	module.exports = function(module) {
  		if(!module.webpackPolyfill) {
  			module.deprecate = function() {};
  			module.paths = [];
  			// module.parent = undefined by default
  			module.children = [];
  			module.webpackPolyfill = 1;
  		}
  		return module;
  	}
  
  
  /***/ },
  /* 14 */
  /***/ function(module, exports) {
  
  	/* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {module.exports = __webpack_amd_options__;
  
  	/* WEBPACK VAR INJECTION */}.call(exports, {}))
  
  /***/ },
  /* 15 */
  /***/ function(module, exports) {
  
  	
  	/**
  	 * Expose `Emitter`.
  	 */
  
  	module.exports = Emitter;
  
  	/**
  	 * Initialize a new `Emitter`.
  	 *
  	 * @api public
  	 */
  
  	function Emitter(obj) {
  	  if (obj) return mixin(obj);
  	};
  
  	/**
  	 * Mixin the emitter properties.
  	 *
  	 * @param {Object} obj
  	 * @return {Object}
  	 * @api private
  	 */
  
  	function mixin(obj) {
  	  for (var key in Emitter.prototype) {
  	    obj[key] = Emitter.prototype[key];
  	  }
  	  return obj;
  	}
  
  	/**
  	 * Listen on the given `event` with `fn`.
  	 *
  	 * @param {String} event
  	 * @param {Function} fn
  	 * @return {Emitter}
  	 * @api public
  	 */
  
  	Emitter.prototype.on =
  	Emitter.prototype.addEventListener = function(event, fn){
  	  this._callbacks = this._callbacks || {};
  	  (this._callbacks[event] = this._callbacks[event] || [])
  	    .push(fn);
  	  return this;
  	};
  
  	/**
  	 * Adds an `event` listener that will be invoked a single
  	 * time then automatically removed.
  	 *
  	 * @param {String} event
  	 * @param {Function} fn
  	 * @return {Emitter}
  	 * @api public
  	 */
  
  	Emitter.prototype.once = function(event, fn){
  	  var self = this;
  	  this._callbacks = this._callbacks || {};
  
  	  function on() {
  	    self.off(event, on);
  	    fn.apply(this, arguments);
  	  }
  
  	  on.fn = fn;
  	  this.on(event, on);
  	  return this;
  	};
  
  	/**
  	 * Remove the given callback for `event` or all
  	 * registered callbacks.
  	 *
  	 * @param {String} event
  	 * @param {Function} fn
  	 * @return {Emitter}
  	 * @api public
  	 */
  
  	Emitter.prototype.off =
  	Emitter.prototype.removeListener =
  	Emitter.prototype.removeAllListeners =
  	Emitter.prototype.removeEventListener = function(event, fn){
  	  this._callbacks = this._callbacks || {};
  
  	  // all
  	  if (0 == arguments.length) {
  	    this._callbacks = {};
  	    return this;
  	  }
  
  	  // specific event
  	  var callbacks = this._callbacks[event];
  	  if (!callbacks) return this;
  
  	  // remove all handlers
  	  if (1 == arguments.length) {
  	    delete this._callbacks[event];
  	    return this;
  	  }
  
  	  // remove specific handler
  	  var cb;
  	  for (var i = 0; i < callbacks.length; i++) {
  	    cb = callbacks[i];
  	    if (cb === fn || cb.fn === fn) {
  	      callbacks.splice(i, 1);
  	      break;
  	    }
  	  }
  	  return this;
  	};
  
  	/**
  	 * Emit `event` with the given args.
  	 *
  	 * @param {String} event
  	 * @param {Mixed} ...
  	 * @return {Emitter}
  	 */
  
  	Emitter.prototype.emit = function(event){
  	  this._callbacks = this._callbacks || {};
  	  var args = [].slice.call(arguments, 1)
  	    , callbacks = this._callbacks[event];
  
  	  if (callbacks) {
  	    callbacks = callbacks.slice(0);
  	    for (var i = 0, len = callbacks.length; i < len; ++i) {
  	      callbacks[i].apply(this, args);
  	    }
  	  }
  
  	  return this;
  	};
  
  	/**
  	 * Return array of callbacks for `event`.
  	 *
  	 * @param {String} event
  	 * @return {Array}
  	 * @api public
  	 */
  
  	Emitter.prototype.listeners = function(event){
  	  this._callbacks = this._callbacks || {};
  	  return this._callbacks[event] || [];
  	};
  
  	/**
  	 * Check if this emitter has `event` handlers.
  	 *
  	 * @param {String} event
  	 * @return {Boolean}
  	 * @api public
  	 */
  
  	Emitter.prototype.hasListeners = function(event){
  	  return !! this.listeners(event).length;
  	};
  
  
  /***/ },
  /* 16 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {/*global Blob,File*/
  
  	/**
  	 * Module requirements
  	 */
  
  	var isArray = __webpack_require__(17);
  	var isBuf = __webpack_require__(18);
  
  	/**
  	 * Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder.
  	 * Anything with blobs or files should be fed through removeBlobs before coming
  	 * here.
  	 *
  	 * @param {Object} packet - socket.io event packet
  	 * @return {Object} with deconstructed packet and list of buffers
  	 * @api public
  	 */
  
  	exports.deconstructPacket = function(packet){
  	  var buffers = [];
  	  var packetData = packet.data;
  
  	  function _deconstructPacket(data) {
  	    if (!data) return data;
  
  	    if (isBuf(data)) {
  	      var placeholder = { _placeholder: true, num: buffers.length };
  	      buffers.push(data);
  	      return placeholder;
  	    } else if (isArray(data)) {
  	      var newData = new Array(data.length);
  	      for (var i = 0; i < data.length; i++) {
  	        newData[i] = _deconstructPacket(data[i]);
  	      }
  	      return newData;
  	    } else if ('object' == typeof data && !(data instanceof Date)) {
  	      var newData = {};
  	      for (var key in data) {
  	        newData[key] = _deconstructPacket(data[key]);
  	      }
  	      return newData;
  	    }
  	    return data;
  	  }
  
  	  var pack = packet;
  	  pack.data = _deconstructPacket(packetData);
  	  pack.attachments = buffers.length; // number of binary 'attachments'
  	  return {packet: pack, buffers: buffers};
  	};
  
  	/**
  	 * Reconstructs a binary packet from its placeholder packet and buffers
  	 *
  	 * @param {Object} packet - event packet with placeholders
  	 * @param {Array} buffers - binary buffers to put in placeholder positions
  	 * @return {Object} reconstructed packet
  	 * @api public
  	 */
  
  	exports.reconstructPacket = function(packet, buffers) {
  	  var curPlaceHolder = 0;
  
  	  function _reconstructPacket(data) {
  	    if (data && data._placeholder) {
  	      var buf = buffers[data.num]; // appropriate buffer (should be natural order anyway)
  	      return buf;
  	    } else if (isArray(data)) {
  	      for (var i = 0; i < data.length; i++) {
  	        data[i] = _reconstructPacket(data[i]);
  	      }
  	      return data;
  	    } else if (data && 'object' == typeof data) {
  	      for (var key in data) {
  	        data[key] = _reconstructPacket(data[key]);
  	      }
  	      return data;
  	    }
  	    return data;
  	  }
  
  	  packet.data = _reconstructPacket(packet.data);
  	  packet.attachments = undefined; // no longer useful
  	  return packet;
  	};
  
  	/**
  	 * Asynchronously removes Blobs or Files from data via
  	 * FileReader's readAsArrayBuffer method. Used before encoding
  	 * data as msgpack. Calls callback with the blobless data.
  	 *
  	 * @param {Object} data
  	 * @param {Function} callback
  	 * @api private
  	 */
  
  	exports.removeBlobs = function(data, callback) {
  	  function _removeBlobs(obj, curKey, containingObject) {
  	    if (!obj) return obj;
  
  	    // convert any blob
  	    if ((global.Blob && obj instanceof Blob) ||
  	        (global.File && obj instanceof File)) {
  	      pendingBlobs++;
  
  	      // async filereader
  	      var fileReader = new FileReader();
  	      fileReader.onload = function() { // this.result == arraybuffer
  	        if (containingObject) {
  	          containingObject[curKey] = this.result;
  	        }
  	        else {
  	          bloblessData = this.result;
  	        }
  
  	        // if nothing pending its callback time
  	        if(! --pendingBlobs) {
  	          callback(bloblessData);
  	        }
  	      };
  
  	      fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer
  	    } else if (isArray(obj)) { // handle array
  	      for (var i = 0; i < obj.length; i++) {
  	        _removeBlobs(obj[i], i, obj);
  	      }
  	    } else if (obj && 'object' == typeof obj && !isBuf(obj)) { // and object
  	      for (var key in obj) {
  	        _removeBlobs(obj[key], key, obj);
  	      }
  	    }
  	  }
  
  	  var pendingBlobs = 0;
  	  var bloblessData = data;
  	  _removeBlobs(bloblessData);
  	  if (!pendingBlobs) {
  	    callback(bloblessData);
  	  }
  	};
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 17 */
  /***/ function(module, exports) {
  
  	module.exports = Array.isArray || function (arr) {
  	  return Object.prototype.toString.call(arr) == '[object Array]';
  	};
  
  
  /***/ },
  /* 18 */
  /***/ function(module, exports) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {
  	module.exports = isBuf;
  
  	/**
  	 * Returns true if obj is a buffer or an arraybuffer.
  	 *
  	 * @api private
  	 */
  
  	function isBuf(obj) {
  	  return (global.Buffer && global.Buffer.isBuffer(obj)) ||
  	         (global.ArrayBuffer && obj instanceof ArrayBuffer);
  	}
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 19 */
  /***/ function(module, exports, __webpack_require__) {
  
  	
  	/**
  	 * Module dependencies.
  	 */
  
  	var eio = __webpack_require__(20);
  	var Socket = __webpack_require__(49);
  	var Emitter = __webpack_require__(50);
  	var parser = __webpack_require__(8);
  	var on = __webpack_require__(52);
  	var bind = __webpack_require__(53);
  	var debug = __webpack_require__(4)('socket.io-client:manager');
  	var indexOf = __webpack_require__(47);
  	var Backoff = __webpack_require__(55);
  
  	/**
  	 * IE6+ hasOwnProperty
  	 */
  
  	var has = Object.prototype.hasOwnProperty;
  
  	/**
  	 * Module exports
  	 */
  
  	module.exports = Manager;
  
  	/**
  	 * `Manager` constructor.
  	 *
  	 * @param {String} engine instance or engine uri/opts
  	 * @param {Object} options
  	 * @api public
  	 */
  
  	function Manager (uri, opts) {
  	  if (!(this instanceof Manager)) return new Manager(uri, opts);
  	  if (uri && ('object' === typeof uri)) {
  	    opts = uri;
  	    uri = undefined;
  	  }
  	  opts = opts || {};
  
  	  opts.path = opts.path || '/socket.io';
  	  this.nsps = {};
  	  this.subs = [];
  	  this.opts = opts;
  	  this.reconnection(opts.reconnection !== false);
  	  this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);
  	  this.reconnectionDelay(opts.reconnectionDelay || 1000);
  	  this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);
  	  this.randomizationFactor(opts.randomizationFactor || 0.5);
  	  this.backoff = new Backoff({
  	    min: this.reconnectionDelay(),
  	    max: this.reconnectionDelayMax(),
  	    jitter: this.randomizationFactor()
  	  });
  	  this.timeout(null == opts.timeout ? 20000 : opts.timeout);
  	  this.readyState = 'closed';
  	  this.uri = uri;
  	  this.connecting = [];
  	  this.lastPing = null;
  	  this.encoding = false;
  	  this.packetBuffer = [];
  	  this.encoder = new parser.Encoder();
  	  this.decoder = new parser.Decoder();
  	  this.autoConnect = opts.autoConnect !== false;
  	  if (this.autoConnect) this.open();
  	}
  
  	/**
  	 * Propagate given event to sockets and emit on `this`
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.emitAll = function () {
  	  this.emit.apply(this, arguments);
  	  for (var nsp in this.nsps) {
  	    if (has.call(this.nsps, nsp)) {
  	      this.nsps[nsp].emit.apply(this.nsps[nsp], arguments);
  	    }
  	  }
  	};
  
  	/**
  	 * Update `socket.id` of all sockets
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.updateSocketIds = function () {
  	  for (var nsp in this.nsps) {
  	    if (has.call(this.nsps, nsp)) {
  	      this.nsps[nsp].id = this.engine.id;
  	    }
  	  }
  	};
  
  	/**
  	 * Mix in `Emitter`.
  	 */
  
  	Emitter(Manager.prototype);
  
  	/**
  	 * Sets the `reconnection` config.
  	 *
  	 * @param {Boolean} true/false if it should automatically reconnect
  	 * @return {Manager} self or value
  	 * @api public
  	 */
  
  	Manager.prototype.reconnection = function (v) {
  	  if (!arguments.length) return this._reconnection;
  	  this._reconnection = !!v;
  	  return this;
  	};
  
  	/**
  	 * Sets the reconnection attempts config.
  	 *
  	 * @param {Number} max reconnection attempts before giving up
  	 * @return {Manager} self or value
  	 * @api public
  	 */
  
  	Manager.prototype.reconnectionAttempts = function (v) {
  	  if (!arguments.length) return this._reconnectionAttempts;
  	  this._reconnectionAttempts = v;
  	  return this;
  	};
  
  	/**
  	 * Sets the delay between reconnections.
  	 *
  	 * @param {Number} delay
  	 * @return {Manager} self or value
  	 * @api public
  	 */
  
  	Manager.prototype.reconnectionDelay = function (v) {
  	  if (!arguments.length) return this._reconnectionDelay;
  	  this._reconnectionDelay = v;
  	  this.backoff && this.backoff.setMin(v);
  	  return this;
  	};
  
  	Manager.prototype.randomizationFactor = function (v) {
  	  if (!arguments.length) return this._randomizationFactor;
  	  this._randomizationFactor = v;
  	  this.backoff && this.backoff.setJitter(v);
  	  return this;
  	};
  
  	/**
  	 * Sets the maximum delay between reconnections.
  	 *
  	 * @param {Number} delay
  	 * @return {Manager} self or value
  	 * @api public
  	 */
  
  	Manager.prototype.reconnectionDelayMax = function (v) {
  	  if (!arguments.length) return this._reconnectionDelayMax;
  	  this._reconnectionDelayMax = v;
  	  this.backoff && this.backoff.setMax(v);
  	  return this;
  	};
  
  	/**
  	 * Sets the connection timeout. `false` to disable
  	 *
  	 * @return {Manager} self or value
  	 * @api public
  	 */
  
  	Manager.prototype.timeout = function (v) {
  	  if (!arguments.length) return this._timeout;
  	  this._timeout = v;
  	  return this;
  	};
  
  	/**
  	 * Starts trying to reconnect if reconnection is enabled and we have not
  	 * started reconnecting yet
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.maybeReconnectOnOpen = function () {
  	  // Only try to reconnect if it's the first time we're connecting
  	  if (!this.reconnecting && this._reconnection && this.backoff.attempts === 0) {
  	    // keeps reconnection from firing twice for the same reconnection loop
  	    this.reconnect();
  	  }
  	};
  
  	/**
  	 * Sets the current transport `socket`.
  	 *
  	 * @param {Function} optional, callback
  	 * @return {Manager} self
  	 * @api public
  	 */
  
  	Manager.prototype.open =
  	Manager.prototype.connect = function (fn, opts) {
  	  debug('readyState %s', this.readyState);
  	  if (~this.readyState.indexOf('open')) return this;
  
  	  debug('opening %s', this.uri);
  	  this.engine = eio(this.uri, this.opts);
  	  var socket = this.engine;
  	  var self = this;
  	  this.readyState = 'opening';
  	  this.skipReconnect = false;
  
  	  // emit `open`
  	  var openSub = on(socket, 'open', function () {
  	    self.onopen();
  	    fn && fn();
  	  });
  
  	  // emit `connect_error`
  	  var errorSub = on(socket, 'error', function (data) {
  	    debug('connect_error');
  	    self.cleanup();
  	    self.readyState = 'closed';
  	    self.emitAll('connect_error', data);
  	    if (fn) {
  	      var err = new Error('Connection error');
  	      err.data = data;
  	      fn(err);
  	    } else {
  	      // Only do this if there is no fn to handle the error
  	      self.maybeReconnectOnOpen();
  	    }
  	  });
  
  	  // emit `connect_timeout`
  	  if (false !== this._timeout) {
  	    var timeout = this._timeout;
  	    debug('connect attempt will timeout after %d', timeout);
  
  	    // set timer
  	    var timer = setTimeout(function () {
  	      debug('connect attempt timed out after %d', timeout);
  	      openSub.destroy();
  	      socket.close();
  	      socket.emit('error', 'timeout');
  	      self.emitAll('connect_timeout', timeout);
  	    }, timeout);
  
  	    this.subs.push({
  	      destroy: function () {
  	        clearTimeout(timer);
  	      }
  	    });
  	  }
  
  	  this.subs.push(openSub);
  	  this.subs.push(errorSub);
  
  	  return this;
  	};
  
  	/**
  	 * Called upon transport open.
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.onopen = function () {
  	  debug('open');
  
  	  // clear old subs
  	  this.cleanup();
  
  	  // mark as open
  	  this.readyState = 'open';
  	  this.emit('open');
  
  	  // add new subs
  	  var socket = this.engine;
  	  this.subs.push(on(socket, 'data', bind(this, 'ondata')));
  	  this.subs.push(on(socket, 'ping', bind(this, 'onping')));
  	  this.subs.push(on(socket, 'pong', bind(this, 'onpong')));
  	  this.subs.push(on(socket, 'error', bind(this, 'onerror')));
  	  this.subs.push(on(socket, 'close', bind(this, 'onclose')));
  	  this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded')));
  	};
  
  	/**
  	 * Called upon a ping.
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.onping = function () {
  	  this.lastPing = new Date();
  	  this.emitAll('ping');
  	};
  
  	/**
  	 * Called upon a packet.
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.onpong = function () {
  	  this.emitAll('pong', new Date() - this.lastPing);
  	};
  
  	/**
  	 * Called with data.
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.ondata = function (data) {
  	  this.decoder.add(data);
  	};
  
  	/**
  	 * Called when parser fully decodes a packet.
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.ondecoded = function (packet) {
  	  this.emit('packet', packet);
  	};
  
  	/**
  	 * Called upon socket error.
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.onerror = function (err) {
  	  debug('error', err);
  	  this.emitAll('error', err);
  	};
  
  	/**
  	 * Creates a new socket for the given `nsp`.
  	 *
  	 * @return {Socket}
  	 * @api public
  	 */
  
  	Manager.prototype.socket = function (nsp, opts) {
  	  var socket = this.nsps[nsp];
  	  if (!socket) {
  	    socket = new Socket(this, nsp, opts);
  	    this.nsps[nsp] = socket;
  	    var self = this;
  	    socket.on('connecting', onConnecting);
  	    socket.on('connect', function () {
  	      socket.id = self.engine.id;
  	    });
  
  	    if (this.autoConnect) {
  	      // manually call here since connecting evnet is fired before listening
  	      onConnecting();
  	    }
  	  }
  
  	  function onConnecting () {
  	    if (!~indexOf(self.connecting, socket)) {
  	      self.connecting.push(socket);
  	    }
  	  }
  
  	  return socket;
  	};
  
  	/**
  	 * Called upon a socket close.
  	 *
  	 * @param {Socket} socket
  	 */
  
  	Manager.prototype.destroy = function (socket) {
  	  var index = indexOf(this.connecting, socket);
  	  if (~index) this.connecting.splice(index, 1);
  	  if (this.connecting.length) return;
  
  	  this.close();
  	};
  
  	/**
  	 * Writes a packet.
  	 *
  	 * @param {Object} packet
  	 * @api private
  	 */
  
  	Manager.prototype.packet = function (packet) {
  	  debug('writing packet %j', packet);
  	  var self = this;
  	  if (packet.query && packet.type === 0) packet.nsp += '?' + packet.query;
  
  	  if (!self.encoding) {
  	    // encode, then write to engine with result
  	    self.encoding = true;
  	    this.encoder.encode(packet, function (encodedPackets) {
  	      for (var i = 0; i < encodedPackets.length; i++) {
  	        self.engine.write(encodedPackets[i], packet.options);
  	      }
  	      self.encoding = false;
  	      self.processPacketQueue();
  	    });
  	  } else { // add packet to the queue
  	    self.packetBuffer.push(packet);
  	  }
  	};
  
  	/**
  	 * If packet buffer is non-empty, begins encoding the
  	 * next packet in line.
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.processPacketQueue = function () {
  	  if (this.packetBuffer.length > 0 && !this.encoding) {
  	    var pack = this.packetBuffer.shift();
  	    this.packet(pack);
  	  }
  	};
  
  	/**
  	 * Clean up transport subscriptions and packet buffer.
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.cleanup = function () {
  	  debug('cleanup');
  
  	  var subsLength = this.subs.length;
  	  for (var i = 0; i < subsLength; i++) {
  	    var sub = this.subs.shift();
  	    sub.destroy();
  	  }
  
  	  this.packetBuffer = [];
  	  this.encoding = false;
  	  this.lastPing = null;
  
  	  this.decoder.destroy();
  	};
  
  	/**
  	 * Close the current socket.
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.close =
  	Manager.prototype.disconnect = function () {
  	  debug('disconnect');
  	  this.skipReconnect = true;
  	  this.reconnecting = false;
  	  if ('opening' === this.readyState) {
  	    // `onclose` will not fire because
  	    // an open event never happened
  	    this.cleanup();
  	  }
  	  this.backoff.reset();
  	  this.readyState = 'closed';
  	  if (this.engine) this.engine.close();
  	};
  
  	/**
  	 * Called upon engine close.
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.onclose = function (reason) {
  	  debug('onclose');
  
  	  this.cleanup();
  	  this.backoff.reset();
  	  this.readyState = 'closed';
  	  this.emit('close', reason);
  
  	  if (this._reconnection && !this.skipReconnect) {
  	    this.reconnect();
  	  }
  	};
  
  	/**
  	 * Attempt a reconnection.
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.reconnect = function () {
  	  if (this.reconnecting || this.skipReconnect) return this;
  
  	  var self = this;
  
  	  if (this.backoff.attempts >= this._reconnectionAttempts) {
  	    debug('reconnect failed');
  	    this.backoff.reset();
  	    this.emitAll('reconnect_failed');
  	    this.reconnecting = false;
  	  } else {
  	    var delay = this.backoff.duration();
  	    debug('will wait %dms before reconnect attempt', delay);
  
  	    this.reconnecting = true;
  	    var timer = setTimeout(function () {
  	      if (self.skipReconnect) return;
  
  	      debug('attempting reconnect');
  	      self.emitAll('reconnect_attempt', self.backoff.attempts);
  	      self.emitAll('reconnecting', self.backoff.attempts);
  
  	      // check again for the case socket closed in above events
  	      if (self.skipReconnect) return;
  
  	      self.open(function (err) {
  	        if (err) {
  	          debug('reconnect attempt error');
  	          self.reconnecting = false;
  	          self.reconnect();
  	          self.emitAll('reconnect_error', err.data);
  	        } else {
  	          debug('reconnect success');
  	          self.onreconnect();
  	        }
  	      });
  	    }, delay);
  
  	    this.subs.push({
  	      destroy: function () {
  	        clearTimeout(timer);
  	      }
  	    });
  	  }
  	};
  
  	/**
  	 * Called upon successful reconnect.
  	 *
  	 * @api private
  	 */
  
  	Manager.prototype.onreconnect = function () {
  	  var attempt = this.backoff.attempts;
  	  this.reconnecting = false;
  	  this.backoff.reset();
  	  this.updateSocketIds();
  	  this.emitAll('reconnect', attempt);
  	};
  
  
  /***/ },
  /* 20 */
  /***/ function(module, exports, __webpack_require__) {
  
  	
  	module.exports = __webpack_require__(21);
  
  
  /***/ },
  /* 21 */
  /***/ function(module, exports, __webpack_require__) {
  
  	
  	module.exports = __webpack_require__(22);
  
  	/**
  	 * Exports parser
  	 *
  	 * @api public
  	 *
  	 */
  	module.exports.parser = __webpack_require__(29);
  
  
  /***/ },
  /* 22 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {/**
  	 * Module dependencies.
  	 */
  
  	var transports = __webpack_require__(23);
  	var Emitter = __webpack_require__(37);
  	var debug = __webpack_require__(41)('engine.io-client:socket');
  	var index = __webpack_require__(47);
  	var parser = __webpack_require__(29);
  	var parseuri = __webpack_require__(3);
  	var parsejson = __webpack_require__(48);
  	var parseqs = __webpack_require__(38);
  
  	/**
  	 * Module exports.
  	 */
  
  	module.exports = Socket;
  
  	/**
  	 * Socket constructor.
  	 *
  	 * @param {String|Object} uri or options
  	 * @param {Object} options
  	 * @api public
  	 */
  
  	function Socket (uri, opts) {
  	  if (!(this instanceof Socket)) return new Socket(uri, opts);
  
  	  opts = opts || {};
  
  	  if (uri && 'object' === typeof uri) {
  	    opts = uri;
  	    uri = null;
  	  }
  
  	  if (uri) {
  	    uri = parseuri(uri);
  	    opts.hostname = uri.host;
  	    opts.secure = uri.protocol === 'https' || uri.protocol === 'wss';
  	    opts.port = uri.port;
  	    if (uri.query) opts.query = uri.query;
  	  } else if (opts.host) {
  	    opts.hostname = parseuri(opts.host).host;
  	  }
  
  	  this.secure = null != opts.secure ? opts.secure
  	    : (global.location && 'https:' === location.protocol);
  
  	  if (opts.hostname && !opts.port) {
  	    // if no port is specified manually, use the protocol default
  	    opts.port = this.secure ? '443' : '80';
  	  }
  
  	  this.agent = opts.agent || false;
  	  this.hostname = opts.hostname ||
  	    (global.location ? location.hostname : 'localhost');
  	  this.port = opts.port || (global.location && location.port
  	      ? location.port
  	      : (this.secure ? 443 : 80));
  	  this.query = opts.query || {};
  	  if ('string' === typeof this.query) this.query = parseqs.decode(this.query);
  	  this.upgrade = false !== opts.upgrade;
  	  this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/';
  	  this.forceJSONP = !!opts.forceJSONP;
  	  this.jsonp = false !== opts.jsonp;
  	  this.forceBase64 = !!opts.forceBase64;
  	  this.enablesXDR = !!opts.enablesXDR;
  	  this.timestampParam = opts.timestampParam || 't';
  	  this.timestampRequests = opts.timestampRequests;
  	  this.transports = opts.transports || ['polling', 'websocket'];
  	  this.readyState = '';
  	  this.writeBuffer = [];
  	  this.prevBufferLen = 0;
  	  this.policyPort = opts.policyPort || 843;
  	  this.rememberUpgrade = opts.rememberUpgrade || false;
  	  this.binaryType = null;
  	  this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
  	  this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || {}) : false;
  
  	  if (true === this.perMessageDeflate) this.perMessageDeflate = {};
  	  if (this.perMessageDeflate && null == this.perMessageDeflate.threshold) {
  	    this.perMessageDeflate.threshold = 1024;
  	  }
  
  	  // SSL options for Node.js client
  	  this.pfx = opts.pfx || null;
  	  this.key = opts.key || null;
  	  this.passphrase = opts.passphrase || null;
  	  this.cert = opts.cert || null;
  	  this.ca = opts.ca || null;
  	  this.ciphers = opts.ciphers || null;
  	  this.rejectUnauthorized = opts.rejectUnauthorized === undefined ? null : opts.rejectUnauthorized;
  	  this.forceNode = !!opts.forceNode;
  
  	  // other options for Node.js client
  	  var freeGlobal = typeof global === 'object' && global;
  	  if (freeGlobal.global === freeGlobal) {
  	    if (opts.extraHeaders && Object.keys(opts.extraHeaders).length > 0) {
  	      this.extraHeaders = opts.extraHeaders;
  	    }
  
  	    if (opts.localAddress) {
  	      this.localAddress = opts.localAddress;
  	    }
  	  }
  
  	  // set on handshake
  	  this.id = null;
  	  this.upgrades = null;
  	  this.pingInterval = null;
  	  this.pingTimeout = null;
  
  	  // set on heartbeat
  	  this.pingIntervalTimer = null;
  	  this.pingTimeoutTimer = null;
  
  	  this.open();
  	}
  
  	Socket.priorWebsocketSuccess = false;
  
  	/**
  	 * Mix in `Emitter`.
  	 */
  
  	Emitter(Socket.prototype);
  
  	/**
  	 * Protocol version.
  	 *
  	 * @api public
  	 */
  
  	Socket.protocol = parser.protocol; // this is an int
  
  	/**
  	 * Expose deps for legacy compatibility
  	 * and standalone browser access.
  	 */
  
  	Socket.Socket = Socket;
  	Socket.Transport = __webpack_require__(28);
  	Socket.transports = __webpack_require__(23);
  	Socket.parser = __webpack_require__(29);
  
  	/**
  	 * Creates transport of the given type.
  	 *
  	 * @param {String} transport name
  	 * @return {Transport}
  	 * @api private
  	 */
  
  	Socket.prototype.createTransport = function (name) {
  	  debug('creating transport "%s"', name);
  	  var query = clone(this.query);
  
  	  // append engine.io protocol identifier
  	  query.EIO = parser.protocol;
  
  	  // transport name
  	  query.transport = name;
  
  	  // session id if we already have one
  	  if (this.id) query.sid = this.id;
  
  	  var transport = new transports[name]({
  	    agent: this.agent,
  	    hostname: this.hostname,
  	    port: this.port,
  	    secure: this.secure,
  	    path: this.path,
  	    query: query,
  	    forceJSONP: this.forceJSONP,
  	    jsonp: this.jsonp,
  	    forceBase64: this.forceBase64,
  	    enablesXDR: this.enablesXDR,
  	    timestampRequests: this.timestampRequests,
  	    timestampParam: this.timestampParam,
  	    policyPort: this.policyPort,
  	    socket: this,
  	    pfx: this.pfx,
  	    key: this.key,
  	    passphrase: this.passphrase,
  	    cert: this.cert,
  	    ca: this.ca,
  	    ciphers: this.ciphers,
  	    rejectUnauthorized: this.rejectUnauthorized,
  	    perMessageDeflate: this.perMessageDeflate,
  	    extraHeaders: this.extraHeaders,
  	    forceNode: this.forceNode,
  	    localAddress: this.localAddress
  	  });
  
  	  return transport;
  	};
  
  	function clone (obj) {
  	  var o = {};
  	  for (var i in obj) {
  	    if (obj.hasOwnProperty(i)) {
  	      o[i] = obj[i];
  	    }
  	  }
  	  return o;
  	}
  
  	/**
  	 * Initializes transport to use and starts probe.
  	 *
  	 * @api private
  	 */
  	Socket.prototype.open = function () {
  	  var transport;
  	  if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') !== -1) {
  	    transport = 'websocket';
  	  } else if (0 === this.transports.length) {
  	    // Emit error on next tick so it can be listened to
  	    var self = this;
  	    setTimeout(function () {
  	      self.emit('error', 'No transports available');
  	    }, 0);
  	    return;
  	  } else {
  	    transport = this.transports[0];
  	  }
  	  this.readyState = 'opening';
  
  	  // Retry with the next transport if the transport is disabled (jsonp: false)
  	  try {
  	    transport = this.createTransport(transport);
  	  } catch (e) {
  	    this.transports.shift();
  	    this.open();
  	    return;
  	  }
  
  	  transport.open();
  	  this.setTransport(transport);
  	};
  
  	/**
  	 * Sets the current transport. Disables the existing one (if any).
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.setTransport = function (transport) {
  	  debug('setting transport %s', transport.name);
  	  var self = this;
  
  	  if (this.transport) {
  	    debug('clearing existing transport %s', this.transport.name);
  	    this.transport.removeAllListeners();
  	  }
  
  	  // set up transport
  	  this.transport = transport;
  
  	  // set up transport listeners
  	  transport
  	  .on('drain', function () {
  	    self.onDrain();
  	  })
  	  .on('packet', function (packet) {
  	    self.onPacket(packet);
  	  })
  	  .on('error', function (e) {
  	    self.onError(e);
  	  })
  	  .on('close', function () {
  	    self.onClose('transport close');
  	  });
  	};
  
  	/**
  	 * Probes a transport.
  	 *
  	 * @param {String} transport name
  	 * @api private
  	 */
  
  	Socket.prototype.probe = function (name) {
  	  debug('probing transport "%s"', name);
  	  var transport = this.createTransport(name, { probe: 1 });
  	  var failed = false;
  	  var self = this;
  
  	  Socket.priorWebsocketSuccess = false;
  
  	  function onTransportOpen () {
  	    if (self.onlyBinaryUpgrades) {
  	      var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
  	      failed = failed || upgradeLosesBinary;
  	    }
  	    if (failed) return;
  
  	    debug('probe transport "%s" opened', name);
  	    transport.send([{ type: 'ping', data: 'probe' }]);
  	    transport.once('packet', function (msg) {
  	      if (failed) return;
  	      if ('pong' === msg.type && 'probe' === msg.data) {
  	        debug('probe transport "%s" pong', name);
  	        self.upgrading = true;
  	        self.emit('upgrading', transport);
  	        if (!transport) return;
  	        Socket.priorWebsocketSuccess = 'websocket' === transport.name;
  
  	        debug('pausing current transport "%s"', self.transport.name);
  	        self.transport.pause(function () {
  	          if (failed) return;
  	          if ('closed' === self.readyState) return;
  	          debug('changing transport and sending upgrade packet');
  
  	          cleanup();
  
  	          self.setTransport(transport);
  	          transport.send([{ type: 'upgrade' }]);
  	          self.emit('upgrade', transport);
  	          transport = null;
  	          self.upgrading = false;
  	          self.flush();
  	        });
  	      } else {
  	        debug('probe transport "%s" failed', name);
  	        var err = new Error('probe error');
  	        err.transport = transport.name;
  	        self.emit('upgradeError', err);
  	      }
  	    });
  	  }
  
  	  function freezeTransport () {
  	    if (failed) return;
  
  	    // Any callback called by transport should be ignored since now
  	    failed = true;
  
  	    cleanup();
  
  	    transport.close();
  	    transport = null;
  	  }
  
  	  // Handle any error that happens while probing
  	  function onerror (err) {
  	    var error = new Error('probe error: ' + err);
  	    error.transport = transport.name;
  
  	    freezeTransport();
  
  	    debug('probe transport "%s" failed because of error: %s', name, err);
  
  	    self.emit('upgradeError', error);
  	  }
  
  	  function onTransportClose () {
  	    onerror('transport closed');
  	  }
  
  	  // When the socket is closed while we're probing
  	  function onclose () {
  	    onerror('socket closed');
  	  }
  
  	  // When the socket is upgraded while we're probing
  	  function onupgrade (to) {
  	    if (transport && to.name !== transport.name) {
  	      debug('"%s" works - aborting "%s"', to.name, transport.name);
  	      freezeTransport();
  	    }
  	  }
  
  	  // Remove all listeners on the transport and on self
  	  function cleanup () {
  	    transport.removeListener('open', onTransportOpen);
  	    transport.removeListener('error', onerror);
  	    transport.removeListener('close', onTransportClose);
  	    self.removeListener('close', onclose);
  	    self.removeListener('upgrading', onupgrade);
  	  }
  
  	  transport.once('open', onTransportOpen);
  	  transport.once('error', onerror);
  	  transport.once('close', onTransportClose);
  
  	  this.once('close', onclose);
  	  this.once('upgrading', onupgrade);
  
  	  transport.open();
  	};
  
  	/**
  	 * Called when connection is deemed open.
  	 *
  	 * @api public
  	 */
  
  	Socket.prototype.onOpen = function () {
  	  debug('socket open');
  	  this.readyState = 'open';
  	  Socket.priorWebsocketSuccess = 'websocket' === this.transport.name;
  	  this.emit('open');
  	  this.flush();
  
  	  // we check for `readyState` in case an `open`
  	  // listener already closed the socket
  	  if ('open' === this.readyState && this.upgrade && this.transport.pause) {
  	    debug('starting upgrade probes');
  	    for (var i = 0, l = this.upgrades.length; i < l; i++) {
  	      this.probe(this.upgrades[i]);
  	    }
  	  }
  	};
  
  	/**
  	 * Handles a packet.
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.onPacket = function (packet) {
  	  if ('opening' === this.readyState || 'open' === this.readyState ||
  	      'closing' === this.readyState) {
  	    debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
  
  	    this.emit('packet', packet);
  
  	    // Socket is live - any packet counts
  	    this.emit('heartbeat');
  
  	    switch (packet.type) {
  	      case 'open':
  	        this.onHandshake(parsejson(packet.data));
  	        break;
  
  	      case 'pong':
  	        this.setPing();
  	        this.emit('pong');
  	        break;
  
  	      case 'error':
  	        var err = new Error('server error');
  	        err.code = packet.data;
  	        this.onError(err);
  	        break;
  
  	      case 'message':
  	        this.emit('data', packet.data);
  	        this.emit('message', packet.data);
  	        break;
  	    }
  	  } else {
  	    debug('packet received with socket readyState "%s"', this.readyState);
  	  }
  	};
  
  	/**
  	 * Called upon handshake completion.
  	 *
  	 * @param {Object} handshake obj
  	 * @api private
  	 */
  
  	Socket.prototype.onHandshake = function (data) {
  	  this.emit('handshake', data);
  	  this.id = data.sid;
  	  this.transport.query.sid = data.sid;
  	  this.upgrades = this.filterUpgrades(data.upgrades);
  	  this.pingInterval = data.pingInterval;
  	  this.pingTimeout = data.pingTimeout;
  	  this.onOpen();
  	  // In case open handler closes socket
  	  if ('closed' === this.readyState) return;
  	  this.setPing();
  
  	  // Prolong liveness of socket on heartbeat
  	  this.removeListener('heartbeat', this.onHeartbeat);
  	  this.on('heartbeat', this.onHeartbeat);
  	};
  
  	/**
  	 * Resets ping timeout.
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.onHeartbeat = function (timeout) {
  	  clearTimeout(this.pingTimeoutTimer);
  	  var self = this;
  	  self.pingTimeoutTimer = setTimeout(function () {
  	    if ('closed' === self.readyState) return;
  	    self.onClose('ping timeout');
  	  }, timeout || (self.pingInterval + self.pingTimeout));
  	};
  
  	/**
  	 * Pings server every `this.pingInterval` and expects response
  	 * within `this.pingTimeout` or closes connection.
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.setPing = function () {
  	  var self = this;
  	  clearTimeout(self.pingIntervalTimer);
  	  self.pingIntervalTimer = setTimeout(function () {
  	    debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
  	    self.ping();
  	    self.onHeartbeat(self.pingTimeout);
  	  }, self.pingInterval);
  	};
  
  	/**
  	* Sends a ping packet.
  	*
  	* @api private
  	*/
  
  	Socket.prototype.ping = function () {
  	  var self = this;
  	  this.sendPacket('ping', function () {
  	    self.emit('ping');
  	  });
  	};
  
  	/**
  	 * Called on `drain` event
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.onDrain = function () {
  	  this.writeBuffer.splice(0, this.prevBufferLen);
  
  	  // setting prevBufferLen = 0 is very important
  	  // for example, when upgrading, upgrade packet is sent over,
  	  // and a nonzero prevBufferLen could cause problems on `drain`
  	  this.prevBufferLen = 0;
  
  	  if (0 === this.writeBuffer.length) {
  	    this.emit('drain');
  	  } else {
  	    this.flush();
  	  }
  	};
  
  	/**
  	 * Flush write buffers.
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.flush = function () {
  	  if ('closed' !== this.readyState && this.transport.writable &&
  	    !this.upgrading && this.writeBuffer.length) {
  	    debug('flushing %d packets in socket', this.writeBuffer.length);
  	    this.transport.send(this.writeBuffer);
  	    // keep track of current length of writeBuffer
  	    // splice writeBuffer and callbackBuffer on `drain`
  	    this.prevBufferLen = this.writeBuffer.length;
  	    this.emit('flush');
  	  }
  	};
  
  	/**
  	 * Sends a message.
  	 *
  	 * @param {String} message.
  	 * @param {Function} callback function.
  	 * @param {Object} options.
  	 * @return {Socket} for chaining.
  	 * @api public
  	 */
  
  	Socket.prototype.write =
  	Socket.prototype.send = function (msg, options, fn) {
  	  this.sendPacket('message', msg, options, fn);
  	  return this;
  	};
  
  	/**
  	 * Sends a packet.
  	 *
  	 * @param {String} packet type.
  	 * @param {String} data.
  	 * @param {Object} options.
  	 * @param {Function} callback function.
  	 * @api private
  	 */
  
  	Socket.prototype.sendPacket = function (type, data, options, fn) {
  	  if ('function' === typeof data) {
  	    fn = data;
  	    data = undefined;
  	  }
  
  	  if ('function' === typeof options) {
  	    fn = options;
  	    options = null;
  	  }
  
  	  if ('closing' === this.readyState || 'closed' === this.readyState) {
  	    return;
  	  }
  
  	  options = options || {};
  	  options.compress = false !== options.compress;
  
  	  var packet = {
  	    type: type,
  	    data: data,
  	    options: options
  	  };
  	  this.emit('packetCreate', packet);
  	  this.writeBuffer.push(packet);
  	  if (fn) this.once('flush', fn);
  	  this.flush();
  	};
  
  	/**
  	 * Closes the connection.
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.close = function () {
  	  if ('opening' === this.readyState || 'open' === this.readyState) {
  	    this.readyState = 'closing';
  
  	    var self = this;
  
  	    if (this.writeBuffer.length) {
  	      this.once('drain', function () {
  	        if (this.upgrading) {
  	          waitForUpgrade();
  	        } else {
  	          close();
  	        }
  	      });
  	    } else if (this.upgrading) {
  	      waitForUpgrade();
  	    } else {
  	      close();
  	    }
  	  }
  
  	  function close () {
  	    self.onClose('forced close');
  	    debug('socket closing - telling transport to close');
  	    self.transport.close();
  	  }
  
  	  function cleanupAndClose () {
  	    self.removeListener('upgrade', cleanupAndClose);
  	    self.removeListener('upgradeError', cleanupAndClose);
  	    close();
  	  }
  
  	  function waitForUpgrade () {
  	    // wait for upgrade to finish since we can't send packets while pausing a transport
  	    self.once('upgrade', cleanupAndClose);
  	    self.once('upgradeError', cleanupAndClose);
  	  }
  
  	  return this;
  	};
  
  	/**
  	 * Called upon transport error
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.onError = function (err) {
  	  debug('socket error %j', err);
  	  Socket.priorWebsocketSuccess = false;
  	  this.emit('error', err);
  	  this.onClose('transport error', err);
  	};
  
  	/**
  	 * Called upon transport close.
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.onClose = function (reason, desc) {
  	  if ('opening' === this.readyState || 'open' === this.readyState || 'closing' === this.readyState) {
  	    debug('socket close with reason: "%s"', reason);
  	    var self = this;
  
  	    // clear timers
  	    clearTimeout(this.pingIntervalTimer);
  	    clearTimeout(this.pingTimeoutTimer);
  
  	    // stop event from firing again for transport
  	    this.transport.removeAllListeners('close');
  
  	    // ensure transport won't stay open
  	    this.transport.close();
  
  	    // ignore further transport communication
  	    this.transport.removeAllListeners();
  
  	    // set ready state
  	    this.readyState = 'closed';
  
  	    // clear session id
  	    this.id = null;
  
  	    // emit close event
  	    this.emit('close', reason, desc);
  
  	    // clean buffers after, so users can still
  	    // grab the buffers on `close` event
  	    self.writeBuffer = [];
  	    self.prevBufferLen = 0;
  	  }
  	};
  
  	/**
  	 * Filters upgrades, returning only those matching client transports.
  	 *
  	 * @param {Array} server upgrades
  	 * @api private
  	 *
  	 */
  
  	Socket.prototype.filterUpgrades = function (upgrades) {
  	  var filteredUpgrades = [];
  	  for (var i = 0, j = upgrades.length; i < j; i++) {
  	    if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]);
  	  }
  	  return filteredUpgrades;
  	};
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 23 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {/**
  	 * Module dependencies
  	 */
  
  	var XMLHttpRequest = __webpack_require__(24);
  	var XHR = __webpack_require__(26);
  	var JSONP = __webpack_require__(44);
  	var websocket = __webpack_require__(45);
  
  	/**
  	 * Export transports.
  	 */
  
  	exports.polling = polling;
  	exports.websocket = websocket;
  
  	/**
  	 * Polling transport polymorphic constructor.
  	 * Decides on xhr vs jsonp based on feature detection.
  	 *
  	 * @api private
  	 */
  
  	function polling (opts) {
  	  var xhr;
  	  var xd = false;
  	  var xs = false;
  	  var jsonp = false !== opts.jsonp;
  
  	  if (global.location) {
  	    var isSSL = 'https:' === location.protocol;
  	    var port = location.port;
  
  	    // some user agents have empty `location.port`
  	    if (!port) {
  	      port = isSSL ? 443 : 80;
  	    }
  
  	    xd = opts.hostname !== location.hostname || port !== opts.port;
  	    xs = opts.secure !== isSSL;
  	  }
  
  	  opts.xdomain = xd;
  	  opts.xscheme = xs;
  	  xhr = new XMLHttpRequest(opts);
  
  	  if ('open' in xhr && !opts.forceJSONP) {
  	    return new XHR(opts);
  	  } else {
  	    if (!jsonp) throw new Error('JSONP disabled');
  	    return new JSONP(opts);
  	  }
  	}
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 24 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {// browser shim for xmlhttprequest module
  
  	var hasCORS = __webpack_require__(25);
  
  	module.exports = function (opts) {
  	  var xdomain = opts.xdomain;
  
  	  // scheme must be same when usign XDomainRequest
  	  // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
  	  var xscheme = opts.xscheme;
  
  	  // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.
  	  // https://github.com/Automattic/engine.io-client/pull/217
  	  var enablesXDR = opts.enablesXDR;
  
  	  // XMLHttpRequest can be disabled on IE
  	  try {
  	    if ('undefined' !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {
  	      return new XMLHttpRequest();
  	    }
  	  } catch (e) { }
  
  	  // Use XDomainRequest for IE8 if enablesXDR is true
  	  // because loading bar keeps flashing when using jsonp-polling
  	  // https://github.com/yujiosaka/socke.io-ie8-loading-example
  	  try {
  	    if ('undefined' !== typeof XDomainRequest && !xscheme && enablesXDR) {
  	      return new XDomainRequest();
  	    }
  	  } catch (e) { }
  
  	  if (!xdomain) {
  	    try {
  	      return new global[['Active'].concat('Object').join('X')]('Microsoft.XMLHTTP');
  	    } catch (e) { }
  	  }
  	};
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 25 */
  /***/ function(module, exports) {
  
  	
  	/**
  	 * Module exports.
  	 *
  	 * Logic borrowed from Modernizr:
  	 *
  	 *   - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js
  	 */
  
  	try {
  	  module.exports = typeof XMLHttpRequest !== 'undefined' &&
  	    'withCredentials' in new XMLHttpRequest();
  	} catch (err) {
  	  // if XMLHttp support is disabled in IE then it will throw
  	  // when trying to create
  	  module.exports = false;
  	}
  
  
  /***/ },
  /* 26 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {/**
  	 * Module requirements.
  	 */
  
  	var XMLHttpRequest = __webpack_require__(24);
  	var Polling = __webpack_require__(27);
  	var Emitter = __webpack_require__(37);
  	var inherit = __webpack_require__(39);
  	var debug = __webpack_require__(41)('engine.io-client:polling-xhr');
  
  	/**
  	 * Module exports.
  	 */
  
  	module.exports = XHR;
  	module.exports.Request = Request;
  
  	/**
  	 * Empty function
  	 */
  
  	function empty () {}
  
  	/**
  	 * XHR Polling constructor.
  	 *
  	 * @param {Object} opts
  	 * @api public
  	 */
  
  	function XHR (opts) {
  	  Polling.call(this, opts);
  	  this.requestTimeout = opts.requestTimeout;
  
  	  if (global.location) {
  	    var isSSL = 'https:' === location.protocol;
  	    var port = location.port;
  
  	    // some user agents have empty `location.port`
  	    if (!port) {
  	      port = isSSL ? 443 : 80;
  	    }
  
  	    this.xd = opts.hostname !== global.location.hostname ||
  	      port !== opts.port;
  	    this.xs = opts.secure !== isSSL;
  	  } else {
  	    this.extraHeaders = opts.extraHeaders;
  	  }
  	}
  
  	/**
  	 * Inherits from Polling.
  	 */
  
  	inherit(XHR, Polling);
  
  	/**
  	 * XHR supports binary
  	 */
  
  	XHR.prototype.supportsBinary = true;
  
  	/**
  	 * Creates a request.
  	 *
  	 * @param {String} method
  	 * @api private
  	 */
  
  	XHR.prototype.request = function (opts) {
  	  opts = opts || {};
  	  opts.uri = this.uri();
  	  opts.xd = this.xd;
  	  opts.xs = this.xs;
  	  opts.agent = this.agent || false;
  	  opts.supportsBinary = this.supportsBinary;
  	  opts.enablesXDR = this.enablesXDR;
  
  	  // SSL options for Node.js client
  	  opts.pfx = this.pfx;
  	  opts.key = this.key;
  	  opts.passphrase = this.passphrase;
  	  opts.cert = this.cert;
  	  opts.ca = this.ca;
  	  opts.ciphers = this.ciphers;
  	  opts.rejectUnauthorized = this.rejectUnauthorized;
  	  opts.requestTimeout = this.requestTimeout;
  
  	  // other options for Node.js client
  	  opts.extraHeaders = this.extraHeaders;
  
  	  return new Request(opts);
  	};
  
  	/**
  	 * Sends data.
  	 *
  	 * @param {String} data to send.
  	 * @param {Function} called upon flush.
  	 * @api private
  	 */
  
  	XHR.prototype.doWrite = function (data, fn) {
  	  var isBinary = typeof data !== 'string' && data !== undefined;
  	  var req = this.request({ method: 'POST', data: data, isBinary: isBinary });
  	  var self = this;
  	  req.on('success', fn);
  	  req.on('error', function (err) {
  	    self.onError('xhr post error', err);
  	  });
  	  this.sendXhr = req;
  	};
  
  	/**
  	 * Starts a poll cycle.
  	 *
  	 * @api private
  	 */
  
  	XHR.prototype.doPoll = function () {
  	  debug('xhr poll');
  	  var req = this.request();
  	  var self = this;
  	  req.on('data', function (data) {
  	    self.onData(data);
  	  });
  	  req.on('error', function (err) {
  	    self.onError('xhr poll error', err);
  	  });
  	  this.pollXhr = req;
  	};
  
  	/**
  	 * Request constructor
  	 *
  	 * @param {Object} options
  	 * @api public
  	 */
  
  	function Request (opts) {
  	  this.method = opts.method || 'GET';
  	  this.uri = opts.uri;
  	  this.xd = !!opts.xd;
  	  this.xs = !!opts.xs;
  	  this.async = false !== opts.async;
  	  this.data = undefined !== opts.data ? opts.data : null;
  	  this.agent = opts.agent;
  	  this.isBinary = opts.isBinary;
  	  this.supportsBinary = opts.supportsBinary;
  	  this.enablesXDR = opts.enablesXDR;
  	  this.requestTimeout = opts.requestTimeout;
  
  	  // SSL options for Node.js client
  	  this.pfx = opts.pfx;
  	  this.key = opts.key;
  	  this.passphrase = opts.passphrase;
  	  this.cert = opts.cert;
  	  this.ca = opts.ca;
  	  this.ciphers = opts.ciphers;
  	  this.rejectUnauthorized = opts.rejectUnauthorized;
  
  	  // other options for Node.js client
  	  this.extraHeaders = opts.extraHeaders;
  
  	  this.create();
  	}
  
  	/**
  	 * Mix in `Emitter`.
  	 */
  
  	Emitter(Request.prototype);
  
  	/**
  	 * Creates the XHR object and sends the request.
  	 *
  	 * @api private
  	 */
  
  	Request.prototype.create = function () {
  	  var opts = { agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR };
  
  	  // SSL options for Node.js client
  	  opts.pfx = this.pfx;
  	  opts.key = this.key;
  	  opts.passphrase = this.passphrase;
  	  opts.cert = this.cert;
  	  opts.ca = this.ca;
  	  opts.ciphers = this.ciphers;
  	  opts.rejectUnauthorized = this.rejectUnauthorized;
  
  	  var xhr = this.xhr = new XMLHttpRequest(opts);
  	  var self = this;
  
  	  try {
  	    debug('xhr open %s: %s', this.method, this.uri);
  	    xhr.open(this.method, this.uri, this.async);
  	    try {
  	      if (this.extraHeaders) {
  	        xhr.setDisableHeaderCheck(true);
  	        for (var i in this.extraHeaders) {
  	          if (this.extraHeaders.hasOwnProperty(i)) {
  	            xhr.setRequestHeader(i, this.extraHeaders[i]);
  	          }
  	        }
  	      }
  	    } catch (e) {}
  	    if (this.supportsBinary) {
  	      // This has to be done after open because Firefox is stupid
  	      // http://stackoverflow.com/questions/13216903/get-binary-data-with-xmlhttprequest-in-a-firefox-extension
  	      xhr.responseType = 'arraybuffer';
  	    }
  
  	    if ('POST' === this.method) {
  	      try {
  	        if (this.isBinary) {
  	          xhr.setRequestHeader('Content-type', 'application/octet-stream');
  	        } else {
  	          xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
  	        }
  	      } catch (e) {}
  	    }
  
  	    try {
  	      xhr.setRequestHeader('Accept', '*/*');
  	    } catch (e) {}
  
  	    // ie6 check
  	    if ('withCredentials' in xhr) {
  	      xhr.withCredentials = true;
  	    }
  
  	    if (this.requestTimeout) {
  	      xhr.timeout = this.requestTimeout;
  	    }
  
  	    if (this.hasXDR()) {
  	      xhr.onload = function () {
  	        self.onLoad();
  	      };
  	      xhr.onerror = function () {
  	        self.onError(xhr.responseText);
  	      };
  	    } else {
  	      xhr.onreadystatechange = function () {
  	        if (4 !== xhr.readyState) return;
  	        if (200 === xhr.status || 1223 === xhr.status) {
  	          self.onLoad();
  	        } else {
  	          // make sure the `error` event handler that's user-set
  	          // does not throw in the same tick and gets caught here
  	          setTimeout(function () {
  	            self.onError(xhr.status);
  	          }, 0);
  	        }
  	      };
  	    }
  
  	    debug('xhr data %s', this.data);
  	    xhr.send(this.data);
  	  } catch (e) {
  	    // Need to defer since .create() is called directly fhrom the constructor
  	    // and thus the 'error' event can only be only bound *after* this exception
  	    // occurs.  Therefore, also, we cannot throw here at all.
  	    setTimeout(function () {
  	      self.onError(e);
  	    }, 0);
  	    return;
  	  }
  
  	  if (global.document) {
  	    this.index = Request.requestsCount++;
  	    Request.requests[this.index] = this;
  	  }
  	};
  
  	/**
  	 * Called upon successful response.
  	 *
  	 * @api private
  	 */
  
  	Request.prototype.onSuccess = function () {
  	  this.emit('success');
  	  this.cleanup();
  	};
  
  	/**
  	 * Called if we have data.
  	 *
  	 * @api private
  	 */
  
  	Request.prototype.onData = function (data) {
  	  this.emit('data', data);
  	  this.onSuccess();
  	};
  
  	/**
  	 * Called upon error.
  	 *
  	 * @api private
  	 */
  
  	Request.prototype.onError = function (err) {
  	  this.emit('error', err);
  	  this.cleanup(true);
  	};
  
  	/**
  	 * Cleans up house.
  	 *
  	 * @api private
  	 */
  
  	Request.prototype.cleanup = function (fromError) {
  	  if ('undefined' === typeof this.xhr || null === this.xhr) {
  	    return;
  	  }
  	  // xmlhttprequest
  	  if (this.hasXDR()) {
  	    this.xhr.onload = this.xhr.onerror = empty;
  	  } else {
  	    this.xhr.onreadystatechange = empty;
  	  }
  
  	  if (fromError) {
  	    try {
  	      this.xhr.abort();
  	    } catch (e) {}
  	  }
  
  	  if (global.document) {
  	    delete Request.requests[this.index];
  	  }
  
  	  this.xhr = null;
  	};
  
  	/**
  	 * Called upon load.
  	 *
  	 * @api private
  	 */
  
  	Request.prototype.onLoad = function () {
  	  var data;
  	  try {
  	    var contentType;
  	    try {
  	      contentType = this.xhr.getResponseHeader('Content-Type').split(';')[0];
  	    } catch (e) {}
  	    if (contentType === 'application/octet-stream') {
  	      data = this.xhr.response || this.xhr.responseText;
  	    } else {
  	      if (!this.supportsBinary) {
  	        data = this.xhr.responseText;
  	      } else {
  	        try {
  	          data = String.fromCharCode.apply(null, new Uint8Array(this.xhr.response));
  	        } catch (e) {
  	          var ui8Arr = new Uint8Array(this.xhr.response);
  	          var dataArray = [];
  	          for (var idx = 0, length = ui8Arr.length; idx < length; idx++) {
  	            dataArray.push(ui8Arr[idx]);
  	          }
  
  	          data = String.fromCharCode.apply(null, dataArray);
  	        }
  	      }
  	    }
  	  } catch (e) {
  	    this.onError(e);
  	  }
  	  if (null != data) {
  	    this.onData(data);
  	  }
  	};
  
  	/**
  	 * Check if it has XDomainRequest.
  	 *
  	 * @api private
  	 */
  
  	Request.prototype.hasXDR = function () {
  	  return 'undefined' !== typeof global.XDomainRequest && !this.xs && this.enablesXDR;
  	};
  
  	/**
  	 * Aborts the request.
  	 *
  	 * @api public
  	 */
  
  	Request.prototype.abort = function () {
  	  this.cleanup();
  	};
  
  	/**
  	 * Aborts pending requests when unloading the window. This is needed to prevent
  	 * memory leaks (e.g. when using IE) and to ensure that no spurious error is
  	 * emitted.
  	 */
  
  	Request.requestsCount = 0;
  	Request.requests = {};
  
  	if (global.document) {
  	  if (global.attachEvent) {
  	    global.attachEvent('onunload', unloadHandler);
  	  } else if (global.addEventListener) {
  	    global.addEventListener('beforeunload', unloadHandler, false);
  	  }
  	}
  
  	function unloadHandler () {
  	  for (var i in Request.requests) {
  	    if (Request.requests.hasOwnProperty(i)) {
  	      Request.requests[i].abort();
  	    }
  	  }
  	}
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 27 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/**
  	 * Module dependencies.
  	 */
  
  	var Transport = __webpack_require__(28);
  	var parseqs = __webpack_require__(38);
  	var parser = __webpack_require__(29);
  	var inherit = __webpack_require__(39);
  	var yeast = __webpack_require__(40);
  	var debug = __webpack_require__(41)('engine.io-client:polling');
  
  	/**
  	 * Module exports.
  	 */
  
  	module.exports = Polling;
  
  	/**
  	 * Is XHR2 supported?
  	 */
  
  	var hasXHR2 = (function () {
  	  var XMLHttpRequest = __webpack_require__(24);
  	  var xhr = new XMLHttpRequest({ xdomain: false });
  	  return null != xhr.responseType;
  	})();
  
  	/**
  	 * Polling interface.
  	 *
  	 * @param {Object} opts
  	 * @api private
  	 */
  
  	function Polling (opts) {
  	  var forceBase64 = (opts && opts.forceBase64);
  	  if (!hasXHR2 || forceBase64) {
  	    this.supportsBinary = false;
  	  }
  	  Transport.call(this, opts);
  	}
  
  	/**
  	 * Inherits from Transport.
  	 */
  
  	inherit(Polling, Transport);
  
  	/**
  	 * Transport name.
  	 */
  
  	Polling.prototype.name = 'polling';
  
  	/**
  	 * Opens the socket (triggers polling). We write a PING message to determine
  	 * when the transport is open.
  	 *
  	 * @api private
  	 */
  
  	Polling.prototype.doOpen = function () {
  	  this.poll();
  	};
  
  	/**
  	 * Pauses polling.
  	 *
  	 * @param {Function} callback upon buffers are flushed and transport is paused
  	 * @api private
  	 */
  
  	Polling.prototype.pause = function (onPause) {
  	  var self = this;
  
  	  this.readyState = 'pausing';
  
  	  function pause () {
  	    debug('paused');
  	    self.readyState = 'paused';
  	    onPause();
  	  }
  
  	  if (this.polling || !this.writable) {
  	    var total = 0;
  
  	    if (this.polling) {
  	      debug('we are currently polling - waiting to pause');
  	      total++;
  	      this.once('pollComplete', function () {
  	        debug('pre-pause polling complete');
  	        --total || pause();
  	      });
  	    }
  
  	    if (!this.writable) {
  	      debug('we are currently writing - waiting to pause');
  	      total++;
  	      this.once('drain', function () {
  	        debug('pre-pause writing complete');
  	        --total || pause();
  	      });
  	    }
  	  } else {
  	    pause();
  	  }
  	};
  
  	/**
  	 * Starts polling cycle.
  	 *
  	 * @api public
  	 */
  
  	Polling.prototype.poll = function () {
  	  debug('polling');
  	  this.polling = true;
  	  this.doPoll();
  	  this.emit('poll');
  	};
  
  	/**
  	 * Overloads onData to detect payloads.
  	 *
  	 * @api private
  	 */
  
  	Polling.prototype.onData = function (data) {
  	  var self = this;
  	  debug('polling got data %s', data);
  	  var callback = function (packet, index, total) {
  	    // if its the first message we consider the transport open
  	    if ('opening' === self.readyState) {
  	      self.onOpen();
  	    }
  
  	    // if its a close packet, we close the ongoing requests
  	    if ('close' === packet.type) {
  	      self.onClose();
  	      return false;
  	    }
  
  	    // otherwise bypass onData and handle the message
  	    self.onPacket(packet);
  	  };
  
  	  // decode payload
  	  parser.decodePayload(data, this.socket.binaryType, callback);
  
  	  // if an event did not trigger closing
  	  if ('closed' !== this.readyState) {
  	    // if we got data we're not polling
  	    this.polling = false;
  	    this.emit('pollComplete');
  
  	    if ('open' === this.readyState) {
  	      this.poll();
  	    } else {
  	      debug('ignoring poll - transport state "%s"', this.readyState);
  	    }
  	  }
  	};
  
  	/**
  	 * For polling, send a close packet.
  	 *
  	 * @api private
  	 */
  
  	Polling.prototype.doClose = function () {
  	  var self = this;
  
  	  function close () {
  	    debug('writing close packet');
  	    self.write([{ type: 'close' }]);
  	  }
  
  	  if ('open' === this.readyState) {
  	    debug('transport open - closing');
  	    close();
  	  } else {
  	    // in case we're trying to close while
  	    // handshaking is in progress (GH-164)
  	    debug('transport not open - deferring close');
  	    this.once('open', close);
  	  }
  	};
  
  	/**
  	 * Writes a packets payload.
  	 *
  	 * @param {Array} data packets
  	 * @param {Function} drain callback
  	 * @api private
  	 */
  
  	Polling.prototype.write = function (packets) {
  	  var self = this;
  	  this.writable = false;
  	  var callbackfn = function () {
  	    self.writable = true;
  	    self.emit('drain');
  	  };
  
  	  parser.encodePayload(packets, this.supportsBinary, function (data) {
  	    self.doWrite(data, callbackfn);
  	  });
  	};
  
  	/**
  	 * Generates uri for connection.
  	 *
  	 * @api private
  	 */
  
  	Polling.prototype.uri = function () {
  	  var query = this.query || {};
  	  var schema = this.secure ? 'https' : 'http';
  	  var port = '';
  
  	  // cache busting is forced
  	  if (false !== this.timestampRequests) {
  	    query[this.timestampParam] = yeast();
  	  }
  
  	  if (!this.supportsBinary && !query.sid) {
  	    query.b64 = 1;
  	  }
  
  	  query = parseqs.encode(query);
  
  	  // avoid port if default for schema
  	  if (this.port && (('https' === schema && Number(this.port) !== 443) ||
  	     ('http' === schema && Number(this.port) !== 80))) {
  	    port = ':' + this.port;
  	  }
  
  	  // prepend ? to query
  	  if (query.length) {
  	    query = '?' + query;
  	  }
  
  	  var ipv6 = this.hostname.indexOf(':') !== -1;
  	  return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query;
  	};
  
  
  /***/ },
  /* 28 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/**
  	 * Module dependencies.
  	 */
  
  	var parser = __webpack_require__(29);
  	var Emitter = __webpack_require__(37);
  
  	/**
  	 * Module exports.
  	 */
  
  	module.exports = Transport;
  
  	/**
  	 * Transport abstract constructor.
  	 *
  	 * @param {Object} options.
  	 * @api private
  	 */
  
  	function Transport (opts) {
  	  this.path = opts.path;
  	  this.hostname = opts.hostname;
  	  this.port = opts.port;
  	  this.secure = opts.secure;
  	  this.query = opts.query;
  	  this.timestampParam = opts.timestampParam;
  	  this.timestampRequests = opts.timestampRequests;
  	  this.readyState = '';
  	  this.agent = opts.agent || false;
  	  this.socket = opts.socket;
  	  this.enablesXDR = opts.enablesXDR;
  
  	  // SSL options for Node.js client
  	  this.pfx = opts.pfx;
  	  this.key = opts.key;
  	  this.passphrase = opts.passphrase;
  	  this.cert = opts.cert;
  	  this.ca = opts.ca;
  	  this.ciphers = opts.ciphers;
  	  this.rejectUnauthorized = opts.rejectUnauthorized;
  	  this.forceNode = opts.forceNode;
  
  	  // other options for Node.js client
  	  this.extraHeaders = opts.extraHeaders;
  	  this.localAddress = opts.localAddress;
  	}
  
  	/**
  	 * Mix in `Emitter`.
  	 */
  
  	Emitter(Transport.prototype);
  
  	/**
  	 * Emits an error.
  	 *
  	 * @param {String} str
  	 * @return {Transport} for chaining
  	 * @api public
  	 */
  
  	Transport.prototype.onError = function (msg, desc) {
  	  var err = new Error(msg);
  	  err.type = 'TransportError';
  	  err.description = desc;
  	  this.emit('error', err);
  	  return this;
  	};
  
  	/**
  	 * Opens the transport.
  	 *
  	 * @api public
  	 */
  
  	Transport.prototype.open = function () {
  	  if ('closed' === this.readyState || '' === this.readyState) {
  	    this.readyState = 'opening';
  	    this.doOpen();
  	  }
  
  	  return this;
  	};
  
  	/**
  	 * Closes the transport.
  	 *
  	 * @api private
  	 */
  
  	Transport.prototype.close = function () {
  	  if ('opening' === this.readyState || 'open' === this.readyState) {
  	    this.doClose();
  	    this.onClose();
  	  }
  
  	  return this;
  	};
  
  	/**
  	 * Sends multiple packets.
  	 *
  	 * @param {Array} packets
  	 * @api private
  	 */
  
  	Transport.prototype.send = function (packets) {
  	  if ('open' === this.readyState) {
  	    this.write(packets);
  	  } else {
  	    throw new Error('Transport not open');
  	  }
  	};
  
  	/**
  	 * Called upon open
  	 *
  	 * @api private
  	 */
  
  	Transport.prototype.onOpen = function () {
  	  this.readyState = 'open';
  	  this.writable = true;
  	  this.emit('open');
  	};
  
  	/**
  	 * Called with data.
  	 *
  	 * @param {String} data
  	 * @api private
  	 */
  
  	Transport.prototype.onData = function (data) {
  	  var packet = parser.decodePacket(data, this.socket.binaryType);
  	  this.onPacket(packet);
  	};
  
  	/**
  	 * Called with a decoded packet.
  	 */
  
  	Transport.prototype.onPacket = function (packet) {
  	  this.emit('packet', packet);
  	};
  
  	/**
  	 * Called upon close.
  	 *
  	 * @api private
  	 */
  
  	Transport.prototype.onClose = function () {
  	  this.readyState = 'closed';
  	  this.emit('close');
  	};
  
  
  /***/ },
  /* 29 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {/**
  	 * Module dependencies.
  	 */
  
  	var keys = __webpack_require__(30);
  	var hasBinary = __webpack_require__(31);
  	var sliceBuffer = __webpack_require__(32);
  	var after = __webpack_require__(33);
  	var utf8 = __webpack_require__(34);
  
  	var base64encoder;
  	if (global && global.ArrayBuffer) {
  	  base64encoder = __webpack_require__(35);
  	}
  
  	/**
  	 * Check if we are running an android browser. That requires us to use
  	 * ArrayBuffer with polling transports...
  	 *
  	 * http://ghinda.net/jpeg-blob-ajax-android/
  	 */
  
  	var isAndroid = typeof navigator !== 'undefined' && /Android/i.test(navigator.userAgent);
  
  	/**
  	 * Check if we are running in PhantomJS.
  	 * Uploading a Blob with PhantomJS does not work correctly, as reported here:
  	 * https://github.com/ariya/phantomjs/issues/11395
  	 * @type boolean
  	 */
  	var isPhantomJS = typeof navigator !== 'undefined' && /PhantomJS/i.test(navigator.userAgent);
  
  	/**
  	 * When true, avoids using Blobs to encode payloads.
  	 * @type boolean
  	 */
  	var dontSendBlobs = isAndroid || isPhantomJS;
  
  	/**
  	 * Current protocol version.
  	 */
  
  	exports.protocol = 3;
  
  	/**
  	 * Packet types.
  	 */
  
  	var packets = exports.packets = {
  	    open:     0    // non-ws
  	  , close:    1    // non-ws
  	  , ping:     2
  	  , pong:     3
  	  , message:  4
  	  , upgrade:  5
  	  , noop:     6
  	};
  
  	var packetslist = keys(packets);
  
  	/**
  	 * Premade error packet.
  	 */
  
  	var err = { type: 'error', data: 'parser error' };
  
  	/**
  	 * Create a blob api even for blob builder when vendor prefixes exist
  	 */
  
  	var Blob = __webpack_require__(36);
  
  	/**
  	 * Encodes a packet.
  	 *
  	 *     <packet type id> [ <data> ]
  	 *
  	 * Example:
  	 *
  	 *     5hello world
  	 *     3
  	 *     4
  	 *
  	 * Binary is encoded in an identical principle
  	 *
  	 * @api private
  	 */
  
  	exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) {
  	  if ('function' == typeof supportsBinary) {
  	    callback = supportsBinary;
  	    supportsBinary = false;
  	  }
  
  	  if ('function' == typeof utf8encode) {
  	    callback = utf8encode;
  	    utf8encode = null;
  	  }
  
  	  var data = (packet.data === undefined)
  	    ? undefined
  	    : packet.data.buffer || packet.data;
  
  	  if (global.ArrayBuffer && data instanceof ArrayBuffer) {
  	    return encodeArrayBuffer(packet, supportsBinary, callback);
  	  } else if (Blob && data instanceof global.Blob) {
  	    return encodeBlob(packet, supportsBinary, callback);
  	  }
  
  	  // might be an object with { base64: true, data: dataAsBase64String }
  	  if (data && data.base64) {
  	    return encodeBase64Object(packet, callback);
  	  }
  
  	  // Sending data as a utf-8 string
  	  var encoded = packets[packet.type];
  
  	  // data fragment is optional
  	  if (undefined !== packet.data) {
  	    encoded += utf8encode ? utf8.encode(String(packet.data)) : String(packet.data);
  	  }
  
  	  return callback('' + encoded);
  
  	};
  
  	function encodeBase64Object(packet, callback) {
  	  // packet data is an object { base64: true, data: dataAsBase64String }
  	  var message = 'b' + exports.packets[packet.type] + packet.data.data;
  	  return callback(message);
  	}
  
  	/**
  	 * Encode packet helpers for binary types
  	 */
  
  	function encodeArrayBuffer(packet, supportsBinary, callback) {
  	  if (!supportsBinary) {
  	    return exports.encodeBase64Packet(packet, callback);
  	  }
  
  	  var data = packet.data;
  	  var contentArray = new Uint8Array(data);
  	  var resultBuffer = new Uint8Array(1 + data.byteLength);
  
  	  resultBuffer[0] = packets[packet.type];
  	  for (var i = 0; i < contentArray.length; i++) {
  	    resultBuffer[i+1] = contentArray[i];
  	  }
  
  	  return callback(resultBuffer.buffer);
  	}
  
  	function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) {
  	  if (!supportsBinary) {
  	    return exports.encodeBase64Packet(packet, callback);
  	  }
  
  	  var fr = new FileReader();
  	  fr.onload = function() {
  	    packet.data = fr.result;
  	    exports.encodePacket(packet, supportsBinary, true, callback);
  	  };
  	  return fr.readAsArrayBuffer(packet.data);
  	}
  
  	function encodeBlob(packet, supportsBinary, callback) {
  	  if (!supportsBinary) {
  	    return exports.encodeBase64Packet(packet, callback);
  	  }
  
  	  if (dontSendBlobs) {
  	    return encodeBlobAsArrayBuffer(packet, supportsBinary, callback);
  	  }
  
  	  var length = new Uint8Array(1);
  	  length[0] = packets[packet.type];
  	  var blob = new Blob([length.buffer, packet.data]);
  
  	  return callback(blob);
  	}
  
  	/**
  	 * Encodes a packet with binary data in a base64 string
  	 *
  	 * @param {Object} packet, has `type` and `data`
  	 * @return {String} base64 encoded message
  	 */
  
  	exports.encodeBase64Packet = function(packet, callback) {
  	  var message = 'b' + exports.packets[packet.type];
  	  if (Blob && packet.data instanceof global.Blob) {
  	    var fr = new FileReader();
  	    fr.onload = function() {
  	      var b64 = fr.result.split(',')[1];
  	      callback(message + b64);
  	    };
  	    return fr.readAsDataURL(packet.data);
  	  }
  
  	  var b64data;
  	  try {
  	    b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data));
  	  } catch (e) {
  	    // iPhone Safari doesn't let you apply with typed arrays
  	    var typed = new Uint8Array(packet.data);
  	    var basic = new Array(typed.length);
  	    for (var i = 0; i < typed.length; i++) {
  	      basic[i] = typed[i];
  	    }
  	    b64data = String.fromCharCode.apply(null, basic);
  	  }
  	  message += global.btoa(b64data);
  	  return callback(message);
  	};
  
  	/**
  	 * Decodes a packet. Changes format to Blob if requested.
  	 *
  	 * @return {Object} with `type` and `data` (if any)
  	 * @api private
  	 */
  
  	exports.decodePacket = function (data, binaryType, utf8decode) {
  	  if (data === undefined) {
  	    return err;
  	  }
  	  // String data
  	  if (typeof data == 'string') {
  	    if (data.charAt(0) == 'b') {
  	      return exports.decodeBase64Packet(data.substr(1), binaryType);
  	    }
  
  	    if (utf8decode) {
  	      data = tryDecode(data);
  	      if (data === false) {
  	        return err;
  	      }
  	    }
  	    var type = data.charAt(0);
  
  	    if (Number(type) != type || !packetslist[type]) {
  	      return err;
  	    }
  
  	    if (data.length > 1) {
  	      return { type: packetslist[type], data: data.substring(1) };
  	    } else {
  	      return { type: packetslist[type] };
  	    }
  	  }
  
  	  var asArray = new Uint8Array(data);
  	  var type = asArray[0];
  	  var rest = sliceBuffer(data, 1);
  	  if (Blob && binaryType === 'blob') {
  	    rest = new Blob([rest]);
  	  }
  	  return { type: packetslist[type], data: rest };
  	};
  
  	function tryDecode(data) {
  	  try {
  	    data = utf8.decode(data);
  	  } catch (e) {
  	    return false;
  	  }
  	  return data;
  	}
  
  	/**
  	 * Decodes a packet encoded in a base64 string
  	 *
  	 * @param {String} base64 encoded message
  	 * @return {Object} with `type` and `data` (if any)
  	 */
  
  	exports.decodeBase64Packet = function(msg, binaryType) {
  	  var type = packetslist[msg.charAt(0)];
  	  if (!base64encoder) {
  	    return { type: type, data: { base64: true, data: msg.substr(1) } };
  	  }
  
  	  var data = base64encoder.decode(msg.substr(1));
  
  	  if (binaryType === 'blob' && Blob) {
  	    data = new Blob([data]);
  	  }
  
  	  return { type: type, data: data };
  	};
  
  	/**
  	 * Encodes multiple messages (payload).
  	 *
  	 *     <length>:data
  	 *
  	 * Example:
  	 *
  	 *     11:hello world2:hi
  	 *
  	 * If any contents are binary, they will be encoded as base64 strings. Base64
  	 * encoded strings are marked with a b before the length specifier
  	 *
  	 * @param {Array} packets
  	 * @api private
  	 */
  
  	exports.encodePayload = function (packets, supportsBinary, callback) {
  	  if (typeof supportsBinary == 'function') {
  	    callback = supportsBinary;
  	    supportsBinary = null;
  	  }
  
  	  var isBinary = hasBinary(packets);
  
  	  if (supportsBinary && isBinary) {
  	    if (Blob && !dontSendBlobs) {
  	      return exports.encodePayloadAsBlob(packets, callback);
  	    }
  
  	    return exports.encodePayloadAsArrayBuffer(packets, callback);
  	  }
  
  	  if (!packets.length) {
  	    return callback('0:');
  	  }
  
  	  function setLengthHeader(message) {
  	    return message.length + ':' + message;
  	  }
  
  	  function encodeOne(packet, doneCallback) {
  	    exports.encodePacket(packet, !isBinary ? false : supportsBinary, true, function(message) {
  	      doneCallback(null, setLengthHeader(message));
  	    });
  	  }
  
  	  map(packets, encodeOne, function(err, results) {
  	    return callback(results.join(''));
  	  });
  	};
  
  	/**
  	 * Async array map using after
  	 */
  
  	function map(ary, each, done) {
  	  var result = new Array(ary.length);
  	  var next = after(ary.length, done);
  
  	  var eachWithIndex = function(i, el, cb) {
  	    each(el, function(error, msg) {
  	      result[i] = msg;
  	      cb(error, result);
  	    });
  	  };
  
  	  for (var i = 0; i < ary.length; i++) {
  	    eachWithIndex(i, ary[i], next);
  	  }
  	}
  
  	/*
  	 * Decodes data when a payload is maybe expected. Possible binary contents are
  	 * decoded from their base64 representation
  	 *
  	 * @param {String} data, callback method
  	 * @api public
  	 */
  
  	exports.decodePayload = function (data, binaryType, callback) {
  	  if (typeof data != 'string') {
  	    return exports.decodePayloadAsBinary(data, binaryType, callback);
  	  }
  
  	  if (typeof binaryType === 'function') {
  	    callback = binaryType;
  	    binaryType = null;
  	  }
  
  	  var packet;
  	  if (data == '') {
  	    // parser error - ignoring payload
  	    return callback(err, 0, 1);
  	  }
  
  	  var length = ''
  	    , n, msg;
  
  	  for (var i = 0, l = data.length; i < l; i++) {
  	    var chr = data.charAt(i);
  
  	    if (':' != chr) {
  	      length += chr;
  	    } else {
  	      if ('' == length || (length != (n = Number(length)))) {
  	        // parser error - ignoring payload
  	        return callback(err, 0, 1);
  	      }
  
  	      msg = data.substr(i + 1, n);
  
  	      if (length != msg.length) {
  	        // parser error - ignoring payload
  	        return callback(err, 0, 1);
  	      }
  
  	      if (msg.length) {
  	        packet = exports.decodePacket(msg, binaryType, true);
  
  	        if (err.type == packet.type && err.data == packet.data) {
  	          // parser error in individual packet - ignoring payload
  	          return callback(err, 0, 1);
  	        }
  
  	        var ret = callback(packet, i + n, l);
  	        if (false === ret) return;
  	      }
  
  	      // advance cursor
  	      i += n;
  	      length = '';
  	    }
  	  }
  
  	  if (length != '') {
  	    // parser error - ignoring payload
  	    return callback(err, 0, 1);
  	  }
  
  	};
  
  	/**
  	 * Encodes multiple messages (payload) as binary.
  	 *
  	 * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
  	 * 255><data>
  	 *
  	 * Example:
  	 * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
  	 *
  	 * @param {Array} packets
  	 * @return {ArrayBuffer} encoded payload
  	 * @api private
  	 */
  
  	exports.encodePayloadAsArrayBuffer = function(packets, callback) {
  	  if (!packets.length) {
  	    return callback(new ArrayBuffer(0));
  	  }
  
  	  function encodeOne(packet, doneCallback) {
  	    exports.encodePacket(packet, true, true, function(data) {
  	      return doneCallback(null, data);
  	    });
  	  }
  
  	  map(packets, encodeOne, function(err, encodedPackets) {
  	    var totalLength = encodedPackets.reduce(function(acc, p) {
  	      var len;
  	      if (typeof p === 'string'){
  	        len = p.length;
  	      } else {
  	        len = p.byteLength;
  	      }
  	      return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2
  	    }, 0);
  
  	    var resultArray = new Uint8Array(totalLength);
  
  	    var bufferIndex = 0;
  	    encodedPackets.forEach(function(p) {
  	      var isString = typeof p === 'string';
  	      var ab = p;
  	      if (isString) {
  	        var view = new Uint8Array(p.length);
  	        for (var i = 0; i < p.length; i++) {
  	          view[i] = p.charCodeAt(i);
  	        }
  	        ab = view.buffer;
  	      }
  
  	      if (isString) { // not true binary
  	        resultArray[bufferIndex++] = 0;
  	      } else { // true binary
  	        resultArray[bufferIndex++] = 1;
  	      }
  
  	      var lenStr = ab.byteLength.toString();
  	      for (var i = 0; i < lenStr.length; i++) {
  	        resultArray[bufferIndex++] = parseInt(lenStr[i]);
  	      }
  	      resultArray[bufferIndex++] = 255;
  
  	      var view = new Uint8Array(ab);
  	      for (var i = 0; i < view.length; i++) {
  	        resultArray[bufferIndex++] = view[i];
  	      }
  	    });
  
  	    return callback(resultArray.buffer);
  	  });
  	};
  
  	/**
  	 * Encode as Blob
  	 */
  
  	exports.encodePayloadAsBlob = function(packets, callback) {
  	  function encodeOne(packet, doneCallback) {
  	    exports.encodePacket(packet, true, true, function(encoded) {
  	      var binaryIdentifier = new Uint8Array(1);
  	      binaryIdentifier[0] = 1;
  	      if (typeof encoded === 'string') {
  	        var view = new Uint8Array(encoded.length);
  	        for (var i = 0; i < encoded.length; i++) {
  	          view[i] = encoded.charCodeAt(i);
  	        }
  	        encoded = view.buffer;
  	        binaryIdentifier[0] = 0;
  	      }
  
  	      var len = (encoded instanceof ArrayBuffer)
  	        ? encoded.byteLength
  	        : encoded.size;
  
  	      var lenStr = len.toString();
  	      var lengthAry = new Uint8Array(lenStr.length + 1);
  	      for (var i = 0; i < lenStr.length; i++) {
  	        lengthAry[i] = parseInt(lenStr[i]);
  	      }
  	      lengthAry[lenStr.length] = 255;
  
  	      if (Blob) {
  	        var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]);
  	        doneCallback(null, blob);
  	      }
  	    });
  	  }
  
  	  map(packets, encodeOne, function(err, results) {
  	    return callback(new Blob(results));
  	  });
  	};
  
  	/*
  	 * Decodes data when a payload is maybe expected. Strings are decoded by
  	 * interpreting each byte as a key code for entries marked to start with 0. See
  	 * description of encodePayloadAsBinary
  	 *
  	 * @param {ArrayBuffer} data, callback method
  	 * @api public
  	 */
  
  	exports.decodePayloadAsBinary = function (data, binaryType, callback) {
  	  if (typeof binaryType === 'function') {
  	    callback = binaryType;
  	    binaryType = null;
  	  }
  
  	  var bufferTail = data;
  	  var buffers = [];
  
  	  var numberTooLong = false;
  	  while (bufferTail.byteLength > 0) {
  	    var tailArray = new Uint8Array(bufferTail);
  	    var isString = tailArray[0] === 0;
  	    var msgLength = '';
  
  	    for (var i = 1; ; i++) {
  	      if (tailArray[i] == 255) break;
  
  	      if (msgLength.length > 310) {
  	        numberTooLong = true;
  	        break;
  	      }
  
  	      msgLength += tailArray[i];
  	    }
  
  	    if(numberTooLong) return callback(err, 0, 1);
  
  	    bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length);
  	    msgLength = parseInt(msgLength);
  
  	    var msg = sliceBuffer(bufferTail, 0, msgLength);
  	    if (isString) {
  	      try {
  	        msg = String.fromCharCode.apply(null, new Uint8Array(msg));
  	      } catch (e) {
  	        // iPhone Safari doesn't let you apply to typed arrays
  	        var typed = new Uint8Array(msg);
  	        msg = '';
  	        for (var i = 0; i < typed.length; i++) {
  	          msg += String.fromCharCode(typed[i]);
  	        }
  	      }
  	    }
  
  	    buffers.push(msg);
  	    bufferTail = sliceBuffer(bufferTail, msgLength);
  	  }
  
  	  var total = buffers.length;
  	  buffers.forEach(function(buffer, i) {
  	    callback(exports.decodePacket(buffer, binaryType, true), i, total);
  	  });
  	};
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 30 */
  /***/ function(module, exports) {
  
  	
  	/**
  	 * Gets the keys for an object.
  	 *
  	 * @return {Array} keys
  	 * @api private
  	 */
  
  	module.exports = Object.keys || function keys (obj){
  	  var arr = [];
  	  var has = Object.prototype.hasOwnProperty;
  
  	  for (var i in obj) {
  	    if (has.call(obj, i)) {
  	      arr.push(i);
  	    }
  	  }
  	  return arr;
  	};
  
  
  /***/ },
  /* 31 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {
  	/*
  	 * Module requirements.
  	 */
  
  	var isArray = __webpack_require__(17);
  
  	/**
  	 * Module exports.
  	 */
  
  	module.exports = hasBinary;
  
  	/**
  	 * Checks for binary data.
  	 *
  	 * Right now only Buffer and ArrayBuffer are supported..
  	 *
  	 * @param {Object} anything
  	 * @api public
  	 */
  
  	function hasBinary(data) {
  
  	  function _hasBinary(obj) {
  	    if (!obj) return false;
  
  	    if ( (global.Buffer && global.Buffer.isBuffer(obj)) ||
  	         (global.ArrayBuffer && obj instanceof ArrayBuffer) ||
  	         (global.Blob && obj instanceof Blob) ||
  	         (global.File && obj instanceof File)
  	        ) {
  	      return true;
  	    }
  
  	    if (isArray(obj)) {
  	      for (var i = 0; i < obj.length; i++) {
  	          if (_hasBinary(obj[i])) {
  	              return true;
  	          }
  	      }
  	    } else if (obj && 'object' == typeof obj) {
  	      if (obj.toJSON) {
  	        obj = obj.toJSON();
  	      }
  
  	      for (var key in obj) {
  	        if (Object.prototype.hasOwnProperty.call(obj, key) && _hasBinary(obj[key])) {
  	          return true;
  	        }
  	      }
  	    }
  
  	    return false;
  	  }
  
  	  return _hasBinary(data);
  	}
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 32 */
  /***/ function(module, exports) {
  
  	/**
  	 * An abstraction for slicing an arraybuffer even when
  	 * ArrayBuffer.prototype.slice is not supported
  	 *
  	 * @api public
  	 */
  
  	module.exports = function(arraybuffer, start, end) {
  	  var bytes = arraybuffer.byteLength;
  	  start = start || 0;
  	  end = end || bytes;
  
  	  if (arraybuffer.slice) { return arraybuffer.slice(start, end); }
  
  	  if (start < 0) { start += bytes; }
  	  if (end < 0) { end += bytes; }
  	  if (end > bytes) { end = bytes; }
  
  	  if (start >= bytes || start >= end || bytes === 0) {
  	    return new ArrayBuffer(0);
  	  }
  
  	  var abv = new Uint8Array(arraybuffer);
  	  var result = new Uint8Array(end - start);
  	  for (var i = start, ii = 0; i < end; i++, ii++) {
  	    result[ii] = abv[i];
  	  }
  	  return result.buffer;
  	};
  
  
  /***/ },
  /* 33 */
  /***/ function(module, exports) {
  
  	module.exports = after
  
  	function after(count, callback, err_cb) {
  	    var bail = false
  	    err_cb = err_cb || noop
  	    proxy.count = count
  
  	    return (count === 0) ? callback() : proxy
  
  	    function proxy(err, result) {
  	        if (proxy.count <= 0) {
  	            throw new Error('after called too many times')
  	        }
  	        --proxy.count
  
  	        // after first error, rest are passed to err_cb
  	        if (err) {
  	            bail = true
  	            callback(err)
  	            // future error callbacks will go to error handler
  	            callback = err_cb
  	        } else if (proxy.count === 0 && !bail) {
  	            callback(null, result)
  	        }
  	    }
  	}
  
  	function noop() {}
  
  
  /***/ },
  /* 34 */
  /***/ function(module, exports, __webpack_require__) {
  
  	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/wtf8 v1.0.0 by @mathias */
  	;(function(root) {
  
  		// Detect free variables `exports`
  		var freeExports = typeof exports == 'object' && exports;
  
  		// Detect free variable `module`
  		var freeModule = typeof module == 'object' && module &&
  			module.exports == freeExports && module;
  
  		// Detect free variable `global`, from Node.js or Browserified code,
  		// and use it as `root`
  		var freeGlobal = typeof global == 'object' && global;
  		if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
  			root = freeGlobal;
  		}
  
  		/*--------------------------------------------------------------------------*/
  
  		var stringFromCharCode = String.fromCharCode;
  
  		// Taken from https://mths.be/punycode
  		function ucs2decode(string) {
  			var output = [];
  			var counter = 0;
  			var length = string.length;
  			var value;
  			var extra;
  			while (counter < length) {
  				value = string.charCodeAt(counter++);
  				if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
  					// high surrogate, and there is a next character
  					extra = string.charCodeAt(counter++);
  					if ((extra & 0xFC00) == 0xDC00) { // low surrogate
  						output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
  					} else {
  						// unmatched surrogate; only append this code unit, in case the next
  						// code unit is the high surrogate of a surrogate pair
  						output.push(value);
  						counter--;
  					}
  				} else {
  					output.push(value);
  				}
  			}
  			return output;
  		}
  
  		// Taken from https://mths.be/punycode
  		function ucs2encode(array) {
  			var length = array.length;
  			var index = -1;
  			var value;
  			var output = '';
  			while (++index < length) {
  				value = array[index];
  				if (value > 0xFFFF) {
  					value -= 0x10000;
  					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
  					value = 0xDC00 | value & 0x3FF;
  				}
  				output += stringFromCharCode(value);
  			}
  			return output;
  		}
  
  		/*--------------------------------------------------------------------------*/
  
  		function createByte(codePoint, shift) {
  			return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
  		}
  
  		function encodeCodePoint(codePoint) {
  			if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
  				return stringFromCharCode(codePoint);
  			}
  			var symbol = '';
  			if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
  				symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
  			}
  			else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
  				symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
  				symbol += createByte(codePoint, 6);
  			}
  			else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
  				symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
  				symbol += createByte(codePoint, 12);
  				symbol += createByte(codePoint, 6);
  			}
  			symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
  			return symbol;
  		}
  
  		function wtf8encode(string) {
  			var codePoints = ucs2decode(string);
  			var length = codePoints.length;
  			var index = -1;
  			var codePoint;
  			var byteString = '';
  			while (++index < length) {
  				codePoint = codePoints[index];
  				byteString += encodeCodePoint(codePoint);
  			}
  			return byteString;
  		}
  
  		/*--------------------------------------------------------------------------*/
  
  		function readContinuationByte() {
  			if (byteIndex >= byteCount) {
  				throw Error('Invalid byte index');
  			}
  
  			var continuationByte = byteArray[byteIndex] & 0xFF;
  			byteIndex++;
  
  			if ((continuationByte & 0xC0) == 0x80) {
  				return continuationByte & 0x3F;
  			}
  
  			// If we end up here, it’s not a continuation byte.
  			throw Error('Invalid continuation byte');
  		}
  
  		function decodeSymbol() {
  			var byte1;
  			var byte2;
  			var byte3;
  			var byte4;
  			var codePoint;
  
  			if (byteIndex > byteCount) {
  				throw Error('Invalid byte index');
  			}
  
  			if (byteIndex == byteCount) {
  				return false;
  			}
  
  			// Read the first byte.
  			byte1 = byteArray[byteIndex] & 0xFF;
  			byteIndex++;
  
  			// 1-byte sequence (no continuation bytes)
  			if ((byte1 & 0x80) == 0) {
  				return byte1;
  			}
  
  			// 2-byte sequence
  			if ((byte1 & 0xE0) == 0xC0) {
  				var byte2 = readContinuationByte();
  				codePoint = ((byte1 & 0x1F) << 6) | byte2;
  				if (codePoint >= 0x80) {
  					return codePoint;
  				} else {
  					throw Error('Invalid continuation byte');
  				}
  			}
  
  			// 3-byte sequence (may include unpaired surrogates)
  			if ((byte1 & 0xF0) == 0xE0) {
  				byte2 = readContinuationByte();
  				byte3 = readContinuationByte();
  				codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
  				if (codePoint >= 0x0800) {
  					return codePoint;
  				} else {
  					throw Error('Invalid continuation byte');
  				}
  			}
  
  			// 4-byte sequence
  			if ((byte1 & 0xF8) == 0xF0) {
  				byte2 = readContinuationByte();
  				byte3 = readContinuationByte();
  				byte4 = readContinuationByte();
  				codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) |
  					(byte3 << 0x06) | byte4;
  				if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
  					return codePoint;
  				}
  			}
  
  			throw Error('Invalid WTF-8 detected');
  		}
  
  		var byteArray;
  		var byteCount;
  		var byteIndex;
  		function wtf8decode(byteString) {
  			byteArray = ucs2decode(byteString);
  			byteCount = byteArray.length;
  			byteIndex = 0;
  			var codePoints = [];
  			var tmp;
  			while ((tmp = decodeSymbol()) !== false) {
  				codePoints.push(tmp);
  			}
  			return ucs2encode(codePoints);
  		}
  
  		/*--------------------------------------------------------------------------*/
  
  		var wtf8 = {
  			'version': '1.0.0',
  			'encode': wtf8encode,
  			'decode': wtf8decode
  		};
  
  		// Some AMD build optimizers, like r.js, check for specific condition patterns
  		// like the following:
  		if (
  			true
  		) {
  			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
  				return wtf8;
  			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  		}	else if (freeExports && !freeExports.nodeType) {
  			if (freeModule) { // in Node.js or RingoJS v0.8.0+
  				freeModule.exports = wtf8;
  			} else { // in Narwhal or RingoJS v0.7.0-
  				var object = {};
  				var hasOwnProperty = object.hasOwnProperty;
  				for (var key in wtf8) {
  					hasOwnProperty.call(wtf8, key) && (freeExports[key] = wtf8[key]);
  				}
  			}
  		} else { // in Rhino or a web browser
  			root.wtf8 = wtf8;
  		}
  
  	}(this));
  
  	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(13)(module), (function() { return this; }())))
  
  /***/ },
  /* 35 */
  /***/ function(module, exports) {
  
  	/*
  	 * base64-arraybuffer
  	 * https://github.com/niklasvh/base64-arraybuffer
  	 *
  	 * Copyright (c) 2012 Niklas von Hertzen
  	 * Licensed under the MIT license.
  	 */
  	(function(){
  	  "use strict";
  
  	  var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  
  	  // Use a lookup table to find the index.
  	  var lookup = new Uint8Array(256);
  	  for (var i = 0; i < chars.length; i++) {
  	    lookup[chars.charCodeAt(i)] = i;
  	  }
  
  	  exports.encode = function(arraybuffer) {
  	    var bytes = new Uint8Array(arraybuffer),
  	    i, len = bytes.length, base64 = "";
  
  	    for (i = 0; i < len; i+=3) {
  	      base64 += chars[bytes[i] >> 2];
  	      base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
  	      base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
  	      base64 += chars[bytes[i + 2] & 63];
  	    }
  
  	    if ((len % 3) === 2) {
  	      base64 = base64.substring(0, base64.length - 1) + "=";
  	    } else if (len % 3 === 1) {
  	      base64 = base64.substring(0, base64.length - 2) + "==";
  	    }
  
  	    return base64;
  	  };
  
  	  exports.decode =  function(base64) {
  	    var bufferLength = base64.length * 0.75,
  	    len = base64.length, i, p = 0,
  	    encoded1, encoded2, encoded3, encoded4;
  
  	    if (base64[base64.length - 1] === "=") {
  	      bufferLength--;
  	      if (base64[base64.length - 2] === "=") {
  	        bufferLength--;
  	      }
  	    }
  
  	    var arraybuffer = new ArrayBuffer(bufferLength),
  	    bytes = new Uint8Array(arraybuffer);
  
  	    for (i = 0; i < len; i+=4) {
  	      encoded1 = lookup[base64.charCodeAt(i)];
  	      encoded2 = lookup[base64.charCodeAt(i+1)];
  	      encoded3 = lookup[base64.charCodeAt(i+2)];
  	      encoded4 = lookup[base64.charCodeAt(i+3)];
  
  	      bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
  	      bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
  	      bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
  	    }
  
  	    return arraybuffer;
  	  };
  	})();
  
  
  /***/ },
  /* 36 */
  /***/ function(module, exports) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {/**
  	 * Create a blob builder even when vendor prefixes exist
  	 */
  
  	var BlobBuilder = global.BlobBuilder
  	  || global.WebKitBlobBuilder
  	  || global.MSBlobBuilder
  	  || global.MozBlobBuilder;
  
  	/**
  	 * Check if Blob constructor is supported
  	 */
  
  	var blobSupported = (function() {
  	  try {
  	    var a = new Blob(['hi']);
  	    return a.size === 2;
  	  } catch(e) {
  	    return false;
  	  }
  	})();
  
  	/**
  	 * Check if Blob constructor supports ArrayBufferViews
  	 * Fails in Safari 6, so we need to map to ArrayBuffers there.
  	 */
  
  	var blobSupportsArrayBufferView = blobSupported && (function() {
  	  try {
  	    var b = new Blob([new Uint8Array([1,2])]);
  	    return b.size === 2;
  	  } catch(e) {
  	    return false;
  	  }
  	})();
  
  	/**
  	 * Check if BlobBuilder is supported
  	 */
  
  	var blobBuilderSupported = BlobBuilder
  	  && BlobBuilder.prototype.append
  	  && BlobBuilder.prototype.getBlob;
  
  	/**
  	 * Helper function that maps ArrayBufferViews to ArrayBuffers
  	 * Used by BlobBuilder constructor and old browsers that didn't
  	 * support it in the Blob constructor.
  	 */
  
  	function mapArrayBufferViews(ary) {
  	  for (var i = 0; i < ary.length; i++) {
  	    var chunk = ary[i];
  	    if (chunk.buffer instanceof ArrayBuffer) {
  	      var buf = chunk.buffer;
  
  	      // if this is a subarray, make a copy so we only
  	      // include the subarray region from the underlying buffer
  	      if (chunk.byteLength !== buf.byteLength) {
  	        var copy = new Uint8Array(chunk.byteLength);
  	        copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength));
  	        buf = copy.buffer;
  	      }
  
  	      ary[i] = buf;
  	    }
  	  }
  	}
  
  	function BlobBuilderConstructor(ary, options) {
  	  options = options || {};
  
  	  var bb = new BlobBuilder();
  	  mapArrayBufferViews(ary);
  
  	  for (var i = 0; i < ary.length; i++) {
  	    bb.append(ary[i]);
  	  }
  
  	  return (options.type) ? bb.getBlob(options.type) : bb.getBlob();
  	};
  
  	function BlobConstructor(ary, options) {
  	  mapArrayBufferViews(ary);
  	  return new Blob(ary, options || {});
  	};
  
  	module.exports = (function() {
  	  if (blobSupported) {
  	    return blobSupportsArrayBufferView ? global.Blob : BlobConstructor;
  	  } else if (blobBuilderSupported) {
  	    return BlobBuilderConstructor;
  	  } else {
  	    return undefined;
  	  }
  	})();
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 37 */
  /***/ function(module, exports, __webpack_require__) {
  
  	
  	/**
  	 * Expose `Emitter`.
  	 */
  
  	if (true) {
  	  module.exports = Emitter;
  	}
  
  	/**
  	 * Initialize a new `Emitter`.
  	 *
  	 * @api public
  	 */
  
  	function Emitter(obj) {
  	  if (obj) return mixin(obj);
  	};
  
  	/**
  	 * Mixin the emitter properties.
  	 *
  	 * @param {Object} obj
  	 * @return {Object}
  	 * @api private
  	 */
  
  	function mixin(obj) {
  	  for (var key in Emitter.prototype) {
  	    obj[key] = Emitter.prototype[key];
  	  }
  	  return obj;
  	}
  
  	/**
  	 * Listen on the given `event` with `fn`.
  	 *
  	 * @param {String} event
  	 * @param {Function} fn
  	 * @return {Emitter}
  	 * @api public
  	 */
  
  	Emitter.prototype.on =
  	Emitter.prototype.addEventListener = function(event, fn){
  	  this._callbacks = this._callbacks || {};
  	  (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
  	    .push(fn);
  	  return this;
  	};
  
  	/**
  	 * Adds an `event` listener that will be invoked a single
  	 * time then automatically removed.
  	 *
  	 * @param {String} event
  	 * @param {Function} fn
  	 * @return {Emitter}
  	 * @api public
  	 */
  
  	Emitter.prototype.once = function(event, fn){
  	  function on() {
  	    this.off(event, on);
  	    fn.apply(this, arguments);
  	  }
  
  	  on.fn = fn;
  	  this.on(event, on);
  	  return this;
  	};
  
  	/**
  	 * Remove the given callback for `event` or all
  	 * registered callbacks.
  	 *
  	 * @param {String} event
  	 * @param {Function} fn
  	 * @return {Emitter}
  	 * @api public
  	 */
  
  	Emitter.prototype.off =
  	Emitter.prototype.removeListener =
  	Emitter.prototype.removeAllListeners =
  	Emitter.prototype.removeEventListener = function(event, fn){
  	  this._callbacks = this._callbacks || {};
  
  	  // all
  	  if (0 == arguments.length) {
  	    this._callbacks = {};
  	    return this;
  	  }
  
  	  // specific event
  	  var callbacks = this._callbacks['$' + event];
  	  if (!callbacks) return this;
  
  	  // remove all handlers
  	  if (1 == arguments.length) {
  	    delete this._callbacks['$' + event];
  	    return this;
  	  }
  
  	  // remove specific handler
  	  var cb;
  	  for (var i = 0; i < callbacks.length; i++) {
  	    cb = callbacks[i];
  	    if (cb === fn || cb.fn === fn) {
  	      callbacks.splice(i, 1);
  	      break;
  	    }
  	  }
  	  return this;
  	};
  
  	/**
  	 * Emit `event` with the given args.
  	 *
  	 * @param {String} event
  	 * @param {Mixed} ...
  	 * @return {Emitter}
  	 */
  
  	Emitter.prototype.emit = function(event){
  	  this._callbacks = this._callbacks || {};
  	  var args = [].slice.call(arguments, 1)
  	    , callbacks = this._callbacks['$' + event];
  
  	  if (callbacks) {
  	    callbacks = callbacks.slice(0);
  	    for (var i = 0, len = callbacks.length; i < len; ++i) {
  	      callbacks[i].apply(this, args);
  	    }
  	  }
  
  	  return this;
  	};
  
  	/**
  	 * Return array of callbacks for `event`.
  	 *
  	 * @param {String} event
  	 * @return {Array}
  	 * @api public
  	 */
  
  	Emitter.prototype.listeners = function(event){
  	  this._callbacks = this._callbacks || {};
  	  return this._callbacks['$' + event] || [];
  	};
  
  	/**
  	 * Check if this emitter has `event` handlers.
  	 *
  	 * @param {String} event
  	 * @return {Boolean}
  	 * @api public
  	 */
  
  	Emitter.prototype.hasListeners = function(event){
  	  return !! this.listeners(event).length;
  	};
  
  
  /***/ },
  /* 38 */
  /***/ function(module, exports) {
  
  	/**
  	 * Compiles a querystring
  	 * Returns string representation of the object
  	 *
  	 * @param {Object}
  	 * @api private
  	 */
  
  	exports.encode = function (obj) {
  	  var str = '';
  
  	  for (var i in obj) {
  	    if (obj.hasOwnProperty(i)) {
  	      if (str.length) str += '&';
  	      str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
  	    }
  	  }
  
  	  return str;
  	};
  
  	/**
  	 * Parses a simple querystring into an object
  	 *
  	 * @param {String} qs
  	 * @api private
  	 */
  
  	exports.decode = function(qs){
  	  var qry = {};
  	  var pairs = qs.split('&');
  	  for (var i = 0, l = pairs.length; i < l; i++) {
  	    var pair = pairs[i].split('=');
  	    qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
  	  }
  	  return qry;
  	};
  
  
  /***/ },
  /* 39 */
  /***/ function(module, exports) {
  
  	
  	module.exports = function(a, b){
  	  var fn = function(){};
  	  fn.prototype = b.prototype;
  	  a.prototype = new fn;
  	  a.prototype.constructor = a;
  	};
  
  /***/ },
  /* 40 */
  /***/ function(module, exports) {
  
  	'use strict';
  
  	var alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split('')
  	  , length = 64
  	  , map = {}
  	  , seed = 0
  	  , i = 0
  	  , prev;
  
  	/**
  	 * Return a string representing the specified number.
  	 *
  	 * @param {Number} num The number to convert.
  	 * @returns {String} The string representation of the number.
  	 * @api public
  	 */
  	function encode(num) {
  	  var encoded = '';
  
  	  do {
  	    encoded = alphabet[num % length] + encoded;
  	    num = Math.floor(num / length);
  	  } while (num > 0);
  
  	  return encoded;
  	}
  
  	/**
  	 * Return the integer value specified by the given string.
  	 *
  	 * @param {String} str The string to convert.
  	 * @returns {Number} The integer value represented by the string.
  	 * @api public
  	 */
  	function decode(str) {
  	  var decoded = 0;
  
  	  for (i = 0; i < str.length; i++) {
  	    decoded = decoded * length + map[str.charAt(i)];
  	  }
  
  	  return decoded;
  	}
  
  	/**
  	 * Yeast: A tiny growing id generator.
  	 *
  	 * @returns {String} A unique id.
  	 * @api public
  	 */
  	function yeast() {
  	  var now = encode(+new Date());
  
  	  if (now !== prev) return seed = 0, prev = now;
  	  return now +'.'+ encode(seed++);
  	}
  
  	//
  	// Map each character to its index.
  	//
  	for (; i < length; i++) map[alphabet[i]] = i;
  
  	//
  	// Expose the `yeast`, `encode` and `decode` functions.
  	//
  	yeast.encode = encode;
  	yeast.decode = decode;
  	module.exports = yeast;
  
  
  /***/ },
  /* 41 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(process) {
  	/**
  	 * This is the web browser implementation of `debug()`.
  	 *
  	 * Expose `debug()` as the module.
  	 */
  
  	exports = module.exports = __webpack_require__(42);
  	exports.log = log;
  	exports.formatArgs = formatArgs;
  	exports.save = save;
  	exports.load = load;
  	exports.useColors = useColors;
  	exports.storage = 'undefined' != typeof chrome
  	               && 'undefined' != typeof chrome.storage
  	                  ? chrome.storage.local
  	                  : localstorage();
  
  	/**
  	 * Colors.
  	 */
  
  	exports.colors = [
  	  'lightseagreen',
  	  'forestgreen',
  	  'goldenrod',
  	  'dodgerblue',
  	  'darkorchid',
  	  'crimson'
  	];
  
  	/**
  	 * Currently only WebKit-based Web Inspectors, Firefox >= v31,
  	 * and the Firebug extension (any Firefox version) are known
  	 * to support "%c" CSS customizations.
  	 *
  	 * TODO: add a `localStorage` variable to explicitly enable/disable colors
  	 */
  
  	function useColors() {
  	  // is webkit? http://stackoverflow.com/a/16459606/376773
  	  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
  	  return (typeof document !== 'undefined' && 'WebkitAppearance' in document.documentElement.style) ||
  	    // is firebug? http://stackoverflow.com/a/398120/376773
  	    (window.console && (console.firebug || (console.exception && console.table))) ||
  	    // is firefox >= v31?
  	    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
  	    (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
  	}
  
  	/**
  	 * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
  	 */
  
  	exports.formatters.j = function(v) {
  	  try {
  	    return JSON.stringify(v);
  	  } catch (err) {
  	    return '[UnexpectedJSONParseError]: ' + err.message;
  	  }
  	};
  
  
  	/**
  	 * Colorize log arguments if enabled.
  	 *
  	 * @api public
  	 */
  
  	function formatArgs() {
  	  var args = arguments;
  	  var useColors = this.useColors;
  
  	  args[0] = (useColors ? '%c' : '')
  	    + this.namespace
  	    + (useColors ? ' %c' : ' ')
  	    + args[0]
  	    + (useColors ? '%c ' : ' ')
  	    + '+' + exports.humanize(this.diff);
  
  	  if (!useColors) return args;
  
  	  var c = 'color: ' + this.color;
  	  args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
  
  	  // the final "%c" is somewhat tricky, because there could be other
  	  // arguments passed either before or after the %c, so we need to
  	  // figure out the correct index to insert the CSS into
  	  var index = 0;
  	  var lastC = 0;
  	  args[0].replace(/%[a-z%]/g, function(match) {
  	    if ('%%' === match) return;
  	    index++;
  	    if ('%c' === match) {
  	      // we only are interested in the *last* %c
  	      // (the user may have provided their own)
  	      lastC = index;
  	    }
  	  });
  
  	  args.splice(lastC, 0, c);
  	  return args;
  	}
  
  	/**
  	 * Invokes `console.log()` when available.
  	 * No-op when `console.log` is not a "function".
  	 *
  	 * @api public
  	 */
  
  	function log() {
  	  // this hackery is required for IE8/9, where
  	  // the `console.log` function doesn't have 'apply'
  	  return 'object' === typeof console
  	    && console.log
  	    && Function.prototype.apply.call(console.log, console, arguments);
  	}
  
  	/**
  	 * Save `namespaces`.
  	 *
  	 * @param {String} namespaces
  	 * @api private
  	 */
  
  	function save(namespaces) {
  	  try {
  	    if (null == namespaces) {
  	      exports.storage.removeItem('debug');
  	    } else {
  	      exports.storage.debug = namespaces;
  	    }
  	  } catch(e) {}
  	}
  
  	/**
  	 * Load `namespaces`.
  	 *
  	 * @return {String} returns the previously persisted debug modes
  	 * @api private
  	 */
  
  	function load() {
  	  var r;
  	  try {
  	    return exports.storage.debug;
  	  } catch(e) {}
  
  	  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
  	  if (typeof process !== 'undefined' && 'env' in process) {
  	    return process.env.DEBUG;
  	  }
  	}
  
  	/**
  	 * Enable namespaces listed in `localStorage.debug` initially.
  	 */
  
  	exports.enable(load());
  
  	/**
  	 * Localstorage attempts to return the localstorage.
  	 *
  	 * This is necessary because safari throws
  	 * when a user disables cookies/localstorage
  	 * and you attempt to access it.
  	 *
  	 * @return {LocalStorage}
  	 * @api private
  	 */
  
  	function localstorage(){
  	  try {
  	    return window.localStorage;
  	  } catch (e) {}
  	}
  
  	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5)))
  
  /***/ },
  /* 42 */
  /***/ function(module, exports, __webpack_require__) {
  
  	
  	/**
  	 * This is the common logic for both the Node.js and web browser
  	 * implementations of `debug()`.
  	 *
  	 * Expose `debug()` as the module.
  	 */
  
  	exports = module.exports = debug.debug = debug;
  	exports.coerce = coerce;
  	exports.disable = disable;
  	exports.enable = enable;
  	exports.enabled = enabled;
  	exports.humanize = __webpack_require__(43);
  
  	/**
  	 * The currently active debug mode names, and names to skip.
  	 */
  
  	exports.names = [];
  	exports.skips = [];
  
  	/**
  	 * Map of special "%n" handling functions, for the debug "format" argument.
  	 *
  	 * Valid key names are a single, lowercased letter, i.e. "n".
  	 */
  
  	exports.formatters = {};
  
  	/**
  	 * Previously assigned color.
  	 */
  
  	var prevColor = 0;
  
  	/**
  	 * Previous log timestamp.
  	 */
  
  	var prevTime;
  
  	/**
  	 * Select a color.
  	 *
  	 * @return {Number}
  	 * @api private
  	 */
  
  	function selectColor() {
  	  return exports.colors[prevColor++ % exports.colors.length];
  	}
  
  	/**
  	 * Create a debugger with the given `namespace`.
  	 *
  	 * @param {String} namespace
  	 * @return {Function}
  	 * @api public
  	 */
  
  	function debug(namespace) {
  
  	  // define the `disabled` version
  	  function disabled() {
  	  }
  	  disabled.enabled = false;
  
  	  // define the `enabled` version
  	  function enabled() {
  
  	    var self = enabled;
  
  	    // set `diff` timestamp
  	    var curr = +new Date();
  	    var ms = curr - (prevTime || curr);
  	    self.diff = ms;
  	    self.prev = prevTime;
  	    self.curr = curr;
  	    prevTime = curr;
  
  	    // add the `color` if not set
  	    if (null == self.useColors) self.useColors = exports.useColors();
  	    if (null == self.color && self.useColors) self.color = selectColor();
  
  	    var args = new Array(arguments.length);
  	    for (var i = 0; i < args.length; i++) {
  	      args[i] = arguments[i];
  	    }
  
  	    args[0] = exports.coerce(args[0]);
  
  	    if ('string' !== typeof args[0]) {
  	      // anything else let's inspect with %o
  	      args = ['%o'].concat(args);
  	    }
  
  	    // apply any `formatters` transformations
  	    var index = 0;
  	    args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
  	      // if we encounter an escaped % then don't increase the array index
  	      if (match === '%%') return match;
  	      index++;
  	      var formatter = exports.formatters[format];
  	      if ('function' === typeof formatter) {
  	        var val = args[index];
  	        match = formatter.call(self, val);
  
  	        // now we need to remove `args[index]` since it's inlined in the `format`
  	        args.splice(index, 1);
  	        index--;
  	      }
  	      return match;
  	    });
  
  	    // apply env-specific formatting
  	    args = exports.formatArgs.apply(self, args);
  
  	    var logFn = enabled.log || exports.log || console.log.bind(console);
  	    logFn.apply(self, args);
  	  }
  	  enabled.enabled = true;
  
  	  var fn = exports.enabled(namespace) ? enabled : disabled;
  
  	  fn.namespace = namespace;
  
  	  return fn;
  	}
  
  	/**
  	 * Enables a debug mode by namespaces. This can include modes
  	 * separated by a colon and wildcards.
  	 *
  	 * @param {String} namespaces
  	 * @api public
  	 */
  
  	function enable(namespaces) {
  	  exports.save(namespaces);
  
  	  var split = (namespaces || '').split(/[\s,]+/);
  	  var len = split.length;
  
  	  for (var i = 0; i < len; i++) {
  	    if (!split[i]) continue; // ignore empty strings
  	    namespaces = split[i].replace(/[\\^$+?.()|[\]{}]/g, '\\$&').replace(/\*/g, '.*?');
  	    if (namespaces[0] === '-') {
  	      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
  	    } else {
  	      exports.names.push(new RegExp('^' + namespaces + '$'));
  	    }
  	  }
  	}
  
  	/**
  	 * Disable debug output.
  	 *
  	 * @api public
  	 */
  
  	function disable() {
  	  exports.enable('');
  	}
  
  	/**
  	 * Returns true if the given mode name is enabled, false otherwise.
  	 *
  	 * @param {String} name
  	 * @return {Boolean}
  	 * @api public
  	 */
  
  	function enabled(name) {
  	  var i, len;
  	  for (i = 0, len = exports.skips.length; i < len; i++) {
  	    if (exports.skips[i].test(name)) {
  	      return false;
  	    }
  	  }
  	  for (i = 0, len = exports.names.length; i < len; i++) {
  	    if (exports.names[i].test(name)) {
  	      return true;
  	    }
  	  }
  	  return false;
  	}
  
  	/**
  	 * Coerce `val`.
  	 *
  	 * @param {Mixed} val
  	 * @return {Mixed}
  	 * @api private
  	 */
  
  	function coerce(val) {
  	  if (val instanceof Error) return val.stack || val.message;
  	  return val;
  	}
  
  
  /***/ },
  /* 43 */
  /***/ function(module, exports) {
  
  	/**
  	 * Helpers.
  	 */
  
  	var s = 1000
  	var m = s * 60
  	var h = m * 60
  	var d = h * 24
  	var y = d * 365.25
  
  	/**
  	 * Parse or format the given `val`.
  	 *
  	 * Options:
  	 *
  	 *  - `long` verbose formatting [false]
  	 *
  	 * @param {String|Number} val
  	 * @param {Object} options
  	 * @throws {Error} throw an error if val is not a non-empty string or a number
  	 * @return {String|Number}
  	 * @api public
  	 */
  
  	module.exports = function (val, options) {
  	  options = options || {}
  	  var type = typeof val
  	  if (type === 'string' && val.length > 0) {
  	    return parse(val)
  	  } else if (type === 'number' && isNaN(val) === false) {
  	    return options.long ?
  				fmtLong(val) :
  				fmtShort(val)
  	  }
  	  throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val))
  	}
  
  	/**
  	 * Parse the given `str` and return milliseconds.
  	 *
  	 * @param {String} str
  	 * @return {Number}
  	 * @api private
  	 */
  
  	function parse(str) {
  	  str = String(str)
  	  if (str.length > 10000) {
  	    return
  	  }
  	  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str)
  	  if (!match) {
  	    return
  	  }
  	  var n = parseFloat(match[1])
  	  var type = (match[2] || 'ms').toLowerCase()
  	  switch (type) {
  	    case 'years':
  	    case 'year':
  	    case 'yrs':
  	    case 'yr':
  	    case 'y':
  	      return n * y
  	    case 'days':
  	    case 'day':
  	    case 'd':
  	      return n * d
  	    case 'hours':
  	    case 'hour':
  	    case 'hrs':
  	    case 'hr':
  	    case 'h':
  	      return n * h
  	    case 'minutes':
  	    case 'minute':
  	    case 'mins':
  	    case 'min':
  	    case 'm':
  	      return n * m
  	    case 'seconds':
  	    case 'second':
  	    case 'secs':
  	    case 'sec':
  	    case 's':
  	      return n * s
  	    case 'milliseconds':
  	    case 'millisecond':
  	    case 'msecs':
  	    case 'msec':
  	    case 'ms':
  	      return n
  	    default:
  	      return undefined
  	  }
  	}
  
  	/**
  	 * Short format for `ms`.
  	 *
  	 * @param {Number} ms
  	 * @return {String}
  	 * @api private
  	 */
  
  	function fmtShort(ms) {
  	  if (ms >= d) {
  	    return Math.round(ms / d) + 'd'
  	  }
  	  if (ms >= h) {
  	    return Math.round(ms / h) + 'h'
  	  }
  	  if (ms >= m) {
  	    return Math.round(ms / m) + 'm'
  	  }
  	  if (ms >= s) {
  	    return Math.round(ms / s) + 's'
  	  }
  	  return ms + 'ms'
  	}
  
  	/**
  	 * Long format for `ms`.
  	 *
  	 * @param {Number} ms
  	 * @return {String}
  	 * @api private
  	 */
  
  	function fmtLong(ms) {
  	  return plural(ms, d, 'day') ||
  	    plural(ms, h, 'hour') ||
  	    plural(ms, m, 'minute') ||
  	    plural(ms, s, 'second') ||
  	    ms + ' ms'
  	}
  
  	/**
  	 * Pluralization helper.
  	 */
  
  	function plural(ms, n, name) {
  	  if (ms < n) {
  	    return
  	  }
  	  if (ms < n * 1.5) {
  	    return Math.floor(ms / n) + ' ' + name
  	  }
  	  return Math.ceil(ms / n) + ' ' + name + 's'
  	}
  
  
  /***/ },
  /* 44 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {
  	/**
  	 * Module requirements.
  	 */
  
  	var Polling = __webpack_require__(27);
  	var inherit = __webpack_require__(39);
  
  	/**
  	 * Module exports.
  	 */
  
  	module.exports = JSONPPolling;
  
  	/**
  	 * Cached regular expressions.
  	 */
  
  	var rNewline = /\n/g;
  	var rEscapedNewline = /\\n/g;
  
  	/**
  	 * Global JSONP callbacks.
  	 */
  
  	var callbacks;
  
  	/**
  	 * Noop.
  	 */
  
  	function empty () { }
  
  	/**
  	 * JSONP Polling constructor.
  	 *
  	 * @param {Object} opts.
  	 * @api public
  	 */
  
  	function JSONPPolling (opts) {
  	  Polling.call(this, opts);
  
  	  this.query = this.query || {};
  
  	  // define global callbacks array if not present
  	  // we do this here (lazily) to avoid unneeded global pollution
  	  if (!callbacks) {
  	    // we need to consider multiple engines in the same page
  	    if (!global.___eio) global.___eio = [];
  	    callbacks = global.___eio;
  	  }
  
  	  // callback identifier
  	  this.index = callbacks.length;
  
  	  // add callback to jsonp global
  	  var self = this;
  	  callbacks.push(function (msg) {
  	    self.onData(msg);
  	  });
  
  	  // append to query string
  	  this.query.j = this.index;
  
  	  // prevent spurious errors from being emitted when the window is unloaded
  	  if (global.document && global.addEventListener) {
  	    global.addEventListener('beforeunload', function () {
  	      if (self.script) self.script.onerror = empty;
  	    }, false);
  	  }
  	}
  
  	/**
  	 * Inherits from Polling.
  	 */
  
  	inherit(JSONPPolling, Polling);
  
  	/*
  	 * JSONP only supports binary as base64 encoded strings
  	 */
  
  	JSONPPolling.prototype.supportsBinary = false;
  
  	/**
  	 * Closes the socket.
  	 *
  	 * @api private
  	 */
  
  	JSONPPolling.prototype.doClose = function () {
  	  if (this.script) {
  	    this.script.parentNode.removeChild(this.script);
  	    this.script = null;
  	  }
  
  	  if (this.form) {
  	    this.form.parentNode.removeChild(this.form);
  	    this.form = null;
  	    this.iframe = null;
  	  }
  
  	  Polling.prototype.doClose.call(this);
  	};
  
  	/**
  	 * Starts a poll cycle.
  	 *
  	 * @api private
  	 */
  
  	JSONPPolling.prototype.doPoll = function () {
  	  var self = this;
  	  var script = document.createElement('script');
  
  	  if (this.script) {
  	    this.script.parentNode.removeChild(this.script);
  	    this.script = null;
  	  }
  
  	  script.async = true;
  	  script.src = this.uri();
  	  script.onerror = function (e) {
  	    self.onError('jsonp poll error', e);
  	  };
  
  	  var insertAt = document.getElementsByTagName('script')[0];
  	  if (insertAt) {
  	    insertAt.parentNode.insertBefore(script, insertAt);
  	  } else {
  	    (document.head || document.body).appendChild(script);
  	  }
  	  this.script = script;
  
  	  var isUAgecko = 'undefined' !== typeof navigator && /gecko/i.test(navigator.userAgent);
  
  	  if (isUAgecko) {
  	    setTimeout(function () {
  	      var iframe = document.createElement('iframe');
  	      document.body.appendChild(iframe);
  	      document.body.removeChild(iframe);
  	    }, 100);
  	  }
  	};
  
  	/**
  	 * Writes with a hidden iframe.
  	 *
  	 * @param {String} data to send
  	 * @param {Function} called upon flush.
  	 * @api private
  	 */
  
  	JSONPPolling.prototype.doWrite = function (data, fn) {
  	  var self = this;
  
  	  if (!this.form) {
  	    var form = document.createElement('form');
  	    var area = document.createElement('textarea');
  	    var id = this.iframeId = 'eio_iframe_' + this.index;
  	    var iframe;
  
  	    form.className = 'socketio';
  	    form.style.position = 'absolute';
  	    form.style.top = '-1000px';
  	    form.style.left = '-1000px';
  	    form.target = id;
  	    form.method = 'POST';
  	    form.setAttribute('accept-charset', 'utf-8');
  	    area.name = 'd';
  	    form.appendChild(area);
  	    document.body.appendChild(form);
  
  	    this.form = form;
  	    this.area = area;
  	  }
  
  	  this.form.action = this.uri();
  
  	  function complete () {
  	    initIframe();
  	    fn();
  	  }
  
  	  function initIframe () {
  	    if (self.iframe) {
  	      try {
  	        self.form.removeChild(self.iframe);
  	      } catch (e) {
  	        self.onError('jsonp polling iframe removal error', e);
  	      }
  	    }
  
  	    try {
  	      // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
  	      var html = '<iframe src="javascript:0" name="' + self.iframeId + '">';
  	      iframe = document.createElement(html);
  	    } catch (e) {
  	      iframe = document.createElement('iframe');
  	      iframe.name = self.iframeId;
  	      iframe.src = 'javascript:0';
  	    }
  
  	    iframe.id = self.iframeId;
  
  	    self.form.appendChild(iframe);
  	    self.iframe = iframe;
  	  }
  
  	  initIframe();
  
  	  // escape \n to prevent it from being converted into \r\n by some UAs
  	  // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side
  	  data = data.replace(rEscapedNewline, '\\\n');
  	  this.area.value = data.replace(rNewline, '\\n');
  
  	  try {
  	    this.form.submit();
  	  } catch (e) {}
  
  	  if (this.iframe.attachEvent) {
  	    this.iframe.onreadystatechange = function () {
  	      if (self.iframe.readyState === 'complete') {
  	        complete();
  	      }
  	    };
  	  } else {
  	    this.iframe.onload = complete;
  	  }
  	};
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 45 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {/**
  	 * Module dependencies.
  	 */
  
  	var Transport = __webpack_require__(28);
  	var parser = __webpack_require__(29);
  	var parseqs = __webpack_require__(38);
  	var inherit = __webpack_require__(39);
  	var yeast = __webpack_require__(40);
  	var debug = __webpack_require__(41)('engine.io-client:websocket');
  	var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
  	var NodeWebSocket;
  	if (typeof window === 'undefined') {
  	  try {
  	    NodeWebSocket = __webpack_require__(46);
  	  } catch (e) { }
  	}
  
  	/**
  	 * Get either the `WebSocket` or `MozWebSocket` globals
  	 * in the browser or try to resolve WebSocket-compatible
  	 * interface exposed by `ws` for Node-like environment.
  	 */
  
  	var WebSocket = BrowserWebSocket;
  	if (!WebSocket && typeof window === 'undefined') {
  	  WebSocket = NodeWebSocket;
  	}
  
  	/**
  	 * Module exports.
  	 */
  
  	module.exports = WS;
  
  	/**
  	 * WebSocket transport constructor.
  	 *
  	 * @api {Object} connection options
  	 * @api public
  	 */
  
  	function WS (opts) {
  	  var forceBase64 = (opts && opts.forceBase64);
  	  if (forceBase64) {
  	    this.supportsBinary = false;
  	  }
  	  this.perMessageDeflate = opts.perMessageDeflate;
  	  this.usingBrowserWebSocket = BrowserWebSocket && !opts.forceNode;
  	  if (!this.usingBrowserWebSocket) {
  	    WebSocket = NodeWebSocket;
  	  }
  	  Transport.call(this, opts);
  	}
  
  	/**
  	 * Inherits from Transport.
  	 */
  
  	inherit(WS, Transport);
  
  	/**
  	 * Transport name.
  	 *
  	 * @api public
  	 */
  
  	WS.prototype.name = 'websocket';
  
  	/*
  	 * WebSockets support binary
  	 */
  
  	WS.prototype.supportsBinary = true;
  
  	/**
  	 * Opens socket.
  	 *
  	 * @api private
  	 */
  
  	WS.prototype.doOpen = function () {
  	  if (!this.check()) {
  	    // let probe timeout
  	    return;
  	  }
  
  	  var uri = this.uri();
  	  var protocols = void (0);
  	  var opts = {
  	    agent: this.agent,
  	    perMessageDeflate: this.perMessageDeflate
  	  };
  
  	  // SSL options for Node.js client
  	  opts.pfx = this.pfx;
  	  opts.key = this.key;
  	  opts.passphrase = this.passphrase;
  	  opts.cert = this.cert;
  	  opts.ca = this.ca;
  	  opts.ciphers = this.ciphers;
  	  opts.rejectUnauthorized = this.rejectUnauthorized;
  	  if (this.extraHeaders) {
  	    opts.headers = this.extraHeaders;
  	  }
  	  if (this.localAddress) {
  	    opts.localAddress = this.localAddress;
  	  }
  
  	  try {
  	    this.ws = this.usingBrowserWebSocket ? new WebSocket(uri) : new WebSocket(uri, protocols, opts);
  	  } catch (err) {
  	    return this.emit('error', err);
  	  }
  
  	  if (this.ws.binaryType === undefined) {
  	    this.supportsBinary = false;
  	  }
  
  	  if (this.ws.supports && this.ws.supports.binary) {
  	    this.supportsBinary = true;
  	    this.ws.binaryType = 'nodebuffer';
  	  } else {
  	    this.ws.binaryType = 'arraybuffer';
  	  }
  
  	  this.addEventListeners();
  	};
  
  	/**
  	 * Adds event listeners to the socket
  	 *
  	 * @api private
  	 */
  
  	WS.prototype.addEventListeners = function () {
  	  var self = this;
  
  	  this.ws.onopen = function () {
  	    self.onOpen();
  	  };
  	  this.ws.onclose = function () {
  	    self.onClose();
  	  };
  	  this.ws.onmessage = function (ev) {
  	    self.onData(ev.data);
  	  };
  	  this.ws.onerror = function (e) {
  	    self.onError('websocket error', e);
  	  };
  	};
  
  	/**
  	 * Writes data to socket.
  	 *
  	 * @param {Array} array of packets.
  	 * @api private
  	 */
  
  	WS.prototype.write = function (packets) {
  	  var self = this;
  	  this.writable = false;
  
  	  // encodePacket efficient as it uses WS framing
  	  // no need for encodePayload
  	  var total = packets.length;
  	  for (var i = 0, l = total; i < l; i++) {
  	    (function (packet) {
  	      parser.encodePacket(packet, self.supportsBinary, function (data) {
  	        if (!self.usingBrowserWebSocket) {
  	          // always create a new object (GH-437)
  	          var opts = {};
  	          if (packet.options) {
  	            opts.compress = packet.options.compress;
  	          }
  
  	          if (self.perMessageDeflate) {
  	            var len = 'string' === typeof data ? global.Buffer.byteLength(data) : data.length;
  	            if (len < self.perMessageDeflate.threshold) {
  	              opts.compress = false;
  	            }
  	          }
  	        }
  
  	        // Sometimes the websocket has already been closed but the browser didn't
  	        // have a chance of informing us about it yet, in that case send will
  	        // throw an error
  	        try {
  	          if (self.usingBrowserWebSocket) {
  	            // TypeError is thrown when passing the second argument on Safari
  	            self.ws.send(data);
  	          } else {
  	            self.ws.send(data, opts);
  	          }
  	        } catch (e) {
  	          debug('websocket closed before onclose event');
  	        }
  
  	        --total || done();
  	      });
  	    })(packets[i]);
  	  }
  
  	  function done () {
  	    self.emit('flush');
  
  	    // fake drain
  	    // defer to next tick to allow Socket to clear writeBuffer
  	    setTimeout(function () {
  	      self.writable = true;
  	      self.emit('drain');
  	    }, 0);
  	  }
  	};
  
  	/**
  	 * Called upon close
  	 *
  	 * @api private
  	 */
  
  	WS.prototype.onClose = function () {
  	  Transport.prototype.onClose.call(this);
  	};
  
  	/**
  	 * Closes socket.
  	 *
  	 * @api private
  	 */
  
  	WS.prototype.doClose = function () {
  	  if (typeof this.ws !== 'undefined') {
  	    this.ws.close();
  	  }
  	};
  
  	/**
  	 * Generates uri for connection.
  	 *
  	 * @api private
  	 */
  
  	WS.prototype.uri = function () {
  	  var query = this.query || {};
  	  var schema = this.secure ? 'wss' : 'ws';
  	  var port = '';
  
  	  // avoid port if default for schema
  	  if (this.port && (('wss' === schema && Number(this.port) !== 443) ||
  	    ('ws' === schema && Number(this.port) !== 80))) {
  	    port = ':' + this.port;
  	  }
  
  	  // append timestamp to URI
  	  if (this.timestampRequests) {
  	    query[this.timestampParam] = yeast();
  	  }
  
  	  // communicate binary support capabilities
  	  if (!this.supportsBinary) {
  	    query.b64 = 1;
  	  }
  
  	  query = parseqs.encode(query);
  
  	  // prepend ? to query
  	  if (query.length) {
  	    query = '?' + query;
  	  }
  
  	  var ipv6 = this.hostname.indexOf(':') !== -1;
  	  return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query;
  	};
  
  	/**
  	 * Feature detection for WebSocket.
  	 *
  	 * @return {Boolean} whether this transport is available.
  	 * @api public
  	 */
  
  	WS.prototype.check = function () {
  	  return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name);
  	};
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 46 */
  /***/ function(module, exports) {
  
  	/* (ignored) */
  
  /***/ },
  /* 47 */
  /***/ function(module, exports) {
  
  	
  	var indexOf = [].indexOf;
  
  	module.exports = function(arr, obj){
  	  if (indexOf) return arr.indexOf(obj);
  	  for (var i = 0; i < arr.length; ++i) {
  	    if (arr[i] === obj) return i;
  	  }
  	  return -1;
  	};
  
  /***/ },
  /* 48 */
  /***/ function(module, exports) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {/**
  	 * JSON parse.
  	 *
  	 * @see Based on jQuery#parseJSON (MIT) and JSON2
  	 * @api private
  	 */
  
  	var rvalidchars = /^[\],:{}\s]*$/;
  	var rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
  	var rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
  	var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g;
  	var rtrimLeft = /^\s+/;
  	var rtrimRight = /\s+$/;
  
  	module.exports = function parsejson(data) {
  	  if ('string' != typeof data || !data) {
  	    return null;
  	  }
  
  	  data = data.replace(rtrimLeft, '').replace(rtrimRight, '');
  
  	  // Attempt to parse using the native JSON parser first
  	  if (global.JSON && JSON.parse) {
  	    return JSON.parse(data);
  	  }
  
  	  if (rvalidchars.test(data.replace(rvalidescape, '@')
  	      .replace(rvalidtokens, ']')
  	      .replace(rvalidbraces, ''))) {
  	    return (new Function('return ' + data))();
  	  }
  	};
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 49 */
  /***/ function(module, exports, __webpack_require__) {
  
  	
  	/**
  	 * Module dependencies.
  	 */
  
  	var parser = __webpack_require__(8);
  	var Emitter = __webpack_require__(50);
  	var toArray = __webpack_require__(51);
  	var on = __webpack_require__(52);
  	var bind = __webpack_require__(53);
  	var debug = __webpack_require__(4)('socket.io-client:socket');
  	var hasBin = __webpack_require__(54);
  
  	/**
  	 * Module exports.
  	 */
  
  	module.exports = exports = Socket;
  
  	/**
  	 * Internal events (blacklisted).
  	 * These events can't be emitted by the user.
  	 *
  	 * @api private
  	 */
  
  	var events = {
  	  connect: 1,
  	  connect_error: 1,
  	  connect_timeout: 1,
  	  connecting: 1,
  	  disconnect: 1,
  	  error: 1,
  	  reconnect: 1,
  	  reconnect_attempt: 1,
  	  reconnect_failed: 1,
  	  reconnect_error: 1,
  	  reconnecting: 1,
  	  ping: 1,
  	  pong: 1
  	};
  
  	/**
  	 * Shortcut to `Emitter#emit`.
  	 */
  
  	var emit = Emitter.prototype.emit;
  
  	/**
  	 * `Socket` constructor.
  	 *
  	 * @api public
  	 */
  
  	function Socket (io, nsp, opts) {
  	  this.io = io;
  	  this.nsp = nsp;
  	  this.json = this; // compat
  	  this.ids = 0;
  	  this.acks = {};
  	  this.receiveBuffer = [];
  	  this.sendBuffer = [];
  	  this.connected = false;
  	  this.disconnected = true;
  	  if (opts && opts.query) {
  	    this.query = opts.query;
  	  }
  	  if (this.io.autoConnect) this.open();
  	}
  
  	/**
  	 * Mix in `Emitter`.
  	 */
  
  	Emitter(Socket.prototype);
  
  	/**
  	 * Subscribe to open, close and packet events
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.subEvents = function () {
  	  if (this.subs) return;
  
  	  var io = this.io;
  	  this.subs = [
  	    on(io, 'open', bind(this, 'onopen')),
  	    on(io, 'packet', bind(this, 'onpacket')),
  	    on(io, 'close', bind(this, 'onclose'))
  	  ];
  	};
  
  	/**
  	 * "Opens" the socket.
  	 *
  	 * @api public
  	 */
  
  	Socket.prototype.open =
  	Socket.prototype.connect = function () {
  	  if (this.connected) return this;
  
  	  this.subEvents();
  	  this.io.open(); // ensure open
  	  if ('open' === this.io.readyState) this.onopen();
  	  this.emit('connecting');
  	  return this;
  	};
  
  	/**
  	 * Sends a `message` event.
  	 *
  	 * @return {Socket} self
  	 * @api public
  	 */
  
  	Socket.prototype.send = function () {
  	  var args = toArray(arguments);
  	  args.unshift('message');
  	  this.emit.apply(this, args);
  	  return this;
  	};
  
  	/**
  	 * Override `emit`.
  	 * If the event is in `events`, it's emitted normally.
  	 *
  	 * @param {String} event name
  	 * @return {Socket} self
  	 * @api public
  	 */
  
  	Socket.prototype.emit = function (ev) {
  	  if (events.hasOwnProperty(ev)) {
  	    emit.apply(this, arguments);
  	    return this;
  	  }
  
  	  var args = toArray(arguments);
  	  var parserType = parser.EVENT; // default
  	  if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary
  	  var packet = { type: parserType, data: args };
  
  	  packet.options = {};
  	  packet.options.compress = !this.flags || false !== this.flags.compress;
  
  	  // event ack callback
  	  if ('function' === typeof args[args.length - 1]) {
  	    debug('emitting packet with ack id %d', this.ids);
  	    this.acks[this.ids] = args.pop();
  	    packet.id = this.ids++;
  	  }
  
  	  if (this.connected) {
  	    this.packet(packet);
  	  } else {
  	    this.sendBuffer.push(packet);
  	  }
  
  	  delete this.flags;
  
  	  return this;
  	};
  
  	/**
  	 * Sends a packet.
  	 *
  	 * @param {Object} packet
  	 * @api private
  	 */
  
  	Socket.prototype.packet = function (packet) {
  	  packet.nsp = this.nsp;
  	  this.io.packet(packet);
  	};
  
  	/**
  	 * Called upon engine `open`.
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.onopen = function () {
  	  debug('transport is open - connecting');
  
  	  // write connect packet if necessary
  	  if ('/' !== this.nsp) {
  	    if (this.query) {
  	      this.packet({type: parser.CONNECT, query: this.query});
  	    } else {
  	      this.packet({type: parser.CONNECT});
  	    }
  	  }
  	};
  
  	/**
  	 * Called upon engine `close`.
  	 *
  	 * @param {String} reason
  	 * @api private
  	 */
  
  	Socket.prototype.onclose = function (reason) {
  	  debug('close (%s)', reason);
  	  this.connected = false;
  	  this.disconnected = true;
  	  delete this.id;
  	  this.emit('disconnect', reason);
  	};
  
  	/**
  	 * Called with socket packet.
  	 *
  	 * @param {Object} packet
  	 * @api private
  	 */
  
  	Socket.prototype.onpacket = function (packet) {
  	  if (packet.nsp !== this.nsp) return;
  
  	  switch (packet.type) {
  	    case parser.CONNECT:
  	      this.onconnect();
  	      break;
  
  	    case parser.EVENT:
  	      this.onevent(packet);
  	      break;
  
  	    case parser.BINARY_EVENT:
  	      this.onevent(packet);
  	      break;
  
  	    case parser.ACK:
  	      this.onack(packet);
  	      break;
  
  	    case parser.BINARY_ACK:
  	      this.onack(packet);
  	      break;
  
  	    case parser.DISCONNECT:
  	      this.ondisconnect();
  	      break;
  
  	    case parser.ERROR:
  	      this.emit('error', packet.data);
  	      break;
  	  }
  	};
  
  	/**
  	 * Called upon a server event.
  	 *
  	 * @param {Object} packet
  	 * @api private
  	 */
  
  	Socket.prototype.onevent = function (packet) {
  	  var args = packet.data || [];
  	  debug('emitting event %j', args);
  
  	  if (null != packet.id) {
  	    debug('attaching ack callback to event');
  	    args.push(this.ack(packet.id));
  	  }
  
  	  if (this.connected) {
  	    emit.apply(this, args);
  	  } else {
  	    this.receiveBuffer.push(args);
  	  }
  	};
  
  	/**
  	 * Produces an ack callback to emit with an event.
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.ack = function (id) {
  	  var self = this;
  	  var sent = false;
  	  return function () {
  	    // prevent double callbacks
  	    if (sent) return;
  	    sent = true;
  	    var args = toArray(arguments);
  	    debug('sending ack %j', args);
  
  	    var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK;
  	    self.packet({
  	      type: type,
  	      id: id,
  	      data: args
  	    });
  	  };
  	};
  
  	/**
  	 * Called upon a server acknowlegement.
  	 *
  	 * @param {Object} packet
  	 * @api private
  	 */
  
  	Socket.prototype.onack = function (packet) {
  	  var ack = this.acks[packet.id];
  	  if ('function' === typeof ack) {
  	    debug('calling ack %s with %j', packet.id, packet.data);
  	    ack.apply(this, packet.data);
  	    delete this.acks[packet.id];
  	  } else {
  	    debug('bad ack %s', packet.id);
  	  }
  	};
  
  	/**
  	 * Called upon server connect.
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.onconnect = function () {
  	  this.connected = true;
  	  this.disconnected = false;
  	  this.emit('connect');
  	  this.emitBuffered();
  	};
  
  	/**
  	 * Emit buffered events (received and emitted).
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.emitBuffered = function () {
  	  var i;
  	  for (i = 0; i < this.receiveBuffer.length; i++) {
  	    emit.apply(this, this.receiveBuffer[i]);
  	  }
  	  this.receiveBuffer = [];
  
  	  for (i = 0; i < this.sendBuffer.length; i++) {
  	    this.packet(this.sendBuffer[i]);
  	  }
  	  this.sendBuffer = [];
  	};
  
  	/**
  	 * Called upon server disconnect.
  	 *
  	 * @api private
  	 */
  
  	Socket.prototype.ondisconnect = function () {
  	  debug('server disconnect (%s)', this.nsp);
  	  this.destroy();
  	  this.onclose('io server disconnect');
  	};
  
  	/**
  	 * Called upon forced client/server side disconnections,
  	 * this method ensures the manager stops tracking us and
  	 * that reconnections don't get triggered for this.
  	 *
  	 * @api private.
  	 */
  
  	Socket.prototype.destroy = function () {
  	  if (this.subs) {
  	    // clean subscriptions to avoid reconnections
  	    for (var i = 0; i < this.subs.length; i++) {
  	      this.subs[i].destroy();
  	    }
  	    this.subs = null;
  	  }
  
  	  this.io.destroy(this);
  	};
  
  	/**
  	 * Disconnects the socket manually.
  	 *
  	 * @return {Socket} self
  	 * @api public
  	 */
  
  	Socket.prototype.close =
  	Socket.prototype.disconnect = function () {
  	  if (this.connected) {
  	    debug('performing disconnect (%s)', this.nsp);
  	    this.packet({ type: parser.DISCONNECT });
  	  }
  
  	  // remove socket from pool
  	  this.destroy();
  
  	  if (this.connected) {
  	    // fire events
  	    this.onclose('io client disconnect');
  	  }
  	  return this;
  	};
  
  	/**
  	 * Sets the compress flag.
  	 *
  	 * @param {Boolean} if `true`, compresses the sending data
  	 * @return {Socket} self
  	 * @api public
  	 */
  
  	Socket.prototype.compress = function (compress) {
  	  this.flags = this.flags || {};
  	  this.flags.compress = compress;
  	  return this;
  	};
  
  
  /***/ },
  /* 50 */
  /***/ function(module, exports, __webpack_require__) {
  
  	
  	/**
  	 * Expose `Emitter`.
  	 */
  
  	if (true) {
  	  module.exports = Emitter;
  	}
  
  	/**
  	 * Initialize a new `Emitter`.
  	 *
  	 * @api public
  	 */
  
  	function Emitter(obj) {
  	  if (obj) return mixin(obj);
  	};
  
  	/**
  	 * Mixin the emitter properties.
  	 *
  	 * @param {Object} obj
  	 * @return {Object}
  	 * @api private
  	 */
  
  	function mixin(obj) {
  	  for (var key in Emitter.prototype) {
  	    obj[key] = Emitter.prototype[key];
  	  }
  	  return obj;
  	}
  
  	/**
  	 * Listen on the given `event` with `fn`.
  	 *
  	 * @param {String} event
  	 * @param {Function} fn
  	 * @return {Emitter}
  	 * @api public
  	 */
  
  	Emitter.prototype.on =
  	Emitter.prototype.addEventListener = function(event, fn){
  	  this._callbacks = this._callbacks || {};
  	  (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
  	    .push(fn);
  	  return this;
  	};
  
  	/**
  	 * Adds an `event` listener that will be invoked a single
  	 * time then automatically removed.
  	 *
  	 * @param {String} event
  	 * @param {Function} fn
  	 * @return {Emitter}
  	 * @api public
  	 */
  
  	Emitter.prototype.once = function(event, fn){
  	  function on() {
  	    this.off(event, on);
  	    fn.apply(this, arguments);
  	  }
  
  	  on.fn = fn;
  	  this.on(event, on);
  	  return this;
  	};
  
  	/**
  	 * Remove the given callback for `event` or all
  	 * registered callbacks.
  	 *
  	 * @param {String} event
  	 * @param {Function} fn
  	 * @return {Emitter}
  	 * @api public
  	 */
  
  	Emitter.prototype.off =
  	Emitter.prototype.removeListener =
  	Emitter.prototype.removeAllListeners =
  	Emitter.prototype.removeEventListener = function(event, fn){
  	  this._callbacks = this._callbacks || {};
  
  	  // all
  	  if (0 == arguments.length) {
  	    this._callbacks = {};
  	    return this;
  	  }
  
  	  // specific event
  	  var callbacks = this._callbacks['$' + event];
  	  if (!callbacks) return this;
  
  	  // remove all handlers
  	  if (1 == arguments.length) {
  	    delete this._callbacks['$' + event];
  	    return this;
  	  }
  
  	  // remove specific handler
  	  var cb;
  	  for (var i = 0; i < callbacks.length; i++) {
  	    cb = callbacks[i];
  	    if (cb === fn || cb.fn === fn) {
  	      callbacks.splice(i, 1);
  	      break;
  	    }
  	  }
  	  return this;
  	};
  
  	/**
  	 * Emit `event` with the given args.
  	 *
  	 * @param {String} event
  	 * @param {Mixed} ...
  	 * @return {Emitter}
  	 */
  
  	Emitter.prototype.emit = function(event){
  	  this._callbacks = this._callbacks || {};
  	  var args = [].slice.call(arguments, 1)
  	    , callbacks = this._callbacks['$' + event];
  
  	  if (callbacks) {
  	    callbacks = callbacks.slice(0);
  	    for (var i = 0, len = callbacks.length; i < len; ++i) {
  	      callbacks[i].apply(this, args);
  	    }
  	  }
  
  	  return this;
  	};
  
  	/**
  	 * Return array of callbacks for `event`.
  	 *
  	 * @param {String} event
  	 * @return {Array}
  	 * @api public
  	 */
  
  	Emitter.prototype.listeners = function(event){
  	  this._callbacks = this._callbacks || {};
  	  return this._callbacks['$' + event] || [];
  	};
  
  	/**
  	 * Check if this emitter has `event` handlers.
  	 *
  	 * @param {String} event
  	 * @return {Boolean}
  	 * @api public
  	 */
  
  	Emitter.prototype.hasListeners = function(event){
  	  return !! this.listeners(event).length;
  	};
  
  
  /***/ },
  /* 51 */
  /***/ function(module, exports) {
  
  	module.exports = toArray
  
  	function toArray(list, index) {
  	    var array = []
  
  	    index = index || 0
  
  	    for (var i = index || 0; i < list.length; i++) {
  	        array[i - index] = list[i]
  	    }
  
  	    return array
  	}
  
  
  /***/ },
  /* 52 */
  /***/ function(module, exports) {
  
  	
  	/**
  	 * Module exports.
  	 */
  
  	module.exports = on;
  
  	/**
  	 * Helper for subscriptions.
  	 *
  	 * @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter`
  	 * @param {String} event name
  	 * @param {Function} callback
  	 * @api public
  	 */
  
  	function on (obj, ev, fn) {
  	  obj.on(ev, fn);
  	  return {
  	    destroy: function () {
  	      obj.removeListener(ev, fn);
  	    }
  	  };
  	}
  
  
  /***/ },
  /* 53 */
  /***/ function(module, exports) {
  
  	/**
  	 * Slice reference.
  	 */
  
  	var slice = [].slice;
  
  	/**
  	 * Bind `obj` to `fn`.
  	 *
  	 * @param {Object} obj
  	 * @param {Function|String} fn or string
  	 * @return {Function}
  	 * @api public
  	 */
  
  	module.exports = function(obj, fn){
  	  if ('string' == typeof fn) fn = obj[fn];
  	  if ('function' != typeof fn) throw new Error('bind() requires a function');
  	  var args = slice.call(arguments, 2);
  	  return function(){
  	    return fn.apply(obj, args.concat(slice.call(arguments)));
  	  }
  	};
  
  
  /***/ },
  /* 54 */
  /***/ function(module, exports, __webpack_require__) {
  
  	/* WEBPACK VAR INJECTION */(function(global) {
  	/*
  	 * Module requirements.
  	 */
  
  	var isArray = __webpack_require__(17);
  
  	/**
  	 * Module exports.
  	 */
  
  	module.exports = hasBinary;
  
  	/**
  	 * Checks for binary data.
  	 *
  	 * Right now only Buffer and ArrayBuffer are supported..
  	 *
  	 * @param {Object} anything
  	 * @api public
  	 */
  
  	function hasBinary(data) {
  
  	  function _hasBinary(obj) {
  	    if (!obj) return false;
  
  	    if ( (global.Buffer && global.Buffer.isBuffer && global.Buffer.isBuffer(obj)) ||
  	         (global.ArrayBuffer && obj instanceof ArrayBuffer) ||
  	         (global.Blob && obj instanceof Blob) ||
  	         (global.File && obj instanceof File)
  	        ) {
  	      return true;
  	    }
  
  	    if (isArray(obj)) {
  	      for (var i = 0; i < obj.length; i++) {
  	          if (_hasBinary(obj[i])) {
  	              return true;
  	          }
  	      }
  	    } else if (obj && 'object' == typeof obj) {
  	      // see: https://github.com/Automattic/has-binary/pull/4
  	      if (obj.toJSON && 'function' == typeof obj.toJSON) {
  	        obj = obj.toJSON();
  	      }
  
  	      for (var key in obj) {
  	        if (Object.prototype.hasOwnProperty.call(obj, key) && _hasBinary(obj[key])) {
  	          return true;
  	        }
  	      }
  	    }
  
  	    return false;
  	  }
  
  	  return _hasBinary(data);
  	}
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 55 */
  /***/ function(module, exports) {
  
  	
  	/**
  	 * Expose `Backoff`.
  	 */
  
  	module.exports = Backoff;
  
  	/**
  	 * Initialize backoff timer with `opts`.
  	 *
  	 * - `min` initial timeout in milliseconds [100]
  	 * - `max` max timeout [10000]
  	 * - `jitter` [0]
  	 * - `factor` [2]
  	 *
  	 * @param {Object} opts
  	 * @api public
  	 */
  
  	function Backoff(opts) {
  	  opts = opts || {};
  	  this.ms = opts.min || 100;
  	  this.max = opts.max || 10000;
  	  this.factor = opts.factor || 2;
  	  this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
  	  this.attempts = 0;
  	}
  
  	/**
  	 * Return the backoff duration.
  	 *
  	 * @return {Number}
  	 * @api public
  	 */
  
  	Backoff.prototype.duration = function(){
  	  var ms = this.ms * Math.pow(this.factor, this.attempts++);
  	  if (this.jitter) {
  	    var rand =  Math.random();
  	    var deviation = Math.floor(rand * this.jitter * ms);
  	    ms = (Math.floor(rand * 10) & 1) == 0  ? ms - deviation : ms + deviation;
  	  }
  	  return Math.min(ms, this.max) | 0;
  	};
  
  	/**
  	 * Reset the number of attempts.
  	 *
  	 * @api public
  	 */
  
  	Backoff.prototype.reset = function(){
  	  this.attempts = 0;
  	};
  
  	/**
  	 * Set the minimum duration
  	 *
  	 * @api public
  	 */
  
  	Backoff.prototype.setMin = function(min){
  	  this.ms = min;
  	};
  
  	/**
  	 * Set the maximum duration
  	 *
  	 * @api public
  	 */
  
  	Backoff.prototype.setMax = function(max){
  	  this.max = max;
  	};
  
  	/**
  	 * Set the jitter
  	 *
  	 * @api public
  	 */
  
  	Backoff.prototype.setJitter = function(jitter){
  	  this.jitter = jitter;
  	};
  
  
  
  /***/ },
  /* 56 */
  /***/ function(module, exports, __webpack_require__) {
  
  	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(global) {/*!
  	 *  howler.js v2.0.2
  	 *  howlerjs.com
  	 *
  	 *  (c) 2013-2016, James Simpson of GoldFire Studios
  	 *  goldfirestudios.com
  	 *
  	 *  MIT License
  	 */
  
  	(function() {
  
  	  'use strict';
  
  	  /** Global Methods **/
  	  /***************************************************************************/
  
  	  /**
  	   * Create the global controller. All contained methods and properties apply
  	   * to all sounds that are currently playing or will be in the future.
  	   */
  	  var HowlerGlobal = function() {
  	    this.init();
  	  };
  	  HowlerGlobal.prototype = {
  	    /**
  	     * Initialize the global Howler object.
  	     * @return {Howler}
  	     */
  	    init: function() {
  	      var self = this || Howler;
  
  	      // Internal properties.
  	      self._codecs = {};
  	      self._howls = [];
  	      self._muted = false;
  	      self._volume = 1;
  	      self._canPlayEvent = 'canplaythrough';
  	      self._navigator = (typeof window !== 'undefined' && window.navigator) ? window.navigator : null;
  
  	      // Public properties.
  	      self.masterGain = null;
  	      self.noAudio = false;
  	      self.usingWebAudio = true;
  	      self.autoSuspend = true;
  	      self.ctx = null;
  
  	      // Set to false to disable the auto iOS enabler.
  	      self.mobileAutoEnable = true;
  
  	      // Setup the various state values for global tracking.
  	      self._setup();
  
  	      return self;
  	    },
  
  	    /**
  	     * Get/set the global volume for all sounds.
  	     * @param  {Float} vol Volume from 0.0 to 1.0.
  	     * @return {Howler/Float}     Returns self or current volume.
  	     */
  	    volume: function(vol) {
  	      var self = this || Howler;
  	      vol = parseFloat(vol);
  
  	      // If we don't have an AudioContext created yet, run the setup.
  	      if (!self.ctx) {
  	        setupAudioContext();
  	      }
  
  	      if (typeof vol !== 'undefined' && vol >= 0 && vol <= 1) {
  	        self._volume = vol;
  
  	        // Don't update any of the nodes if we are muted.
  	        if (self._muted) {
  	          return self;
  	        }
  
  	        // When using Web Audio, we just need to adjust the master gain.
  	        if (self.usingWebAudio) {
  	          self.masterGain.gain.value = vol;
  	        }
  
  	        // Loop through and change volume for all HTML5 audio nodes.
  	        for (var i=0; i<self._howls.length; i++) {
  	          if (!self._howls[i]._webAudio) {
  	            // Get all of the sounds in this Howl group.
  	            var ids = self._howls[i]._getSoundIds();
  
  	            // Loop through all sounds and change the volumes.
  	            for (var j=0; j<ids.length; j++) {
  	              var sound = self._howls[i]._soundById(ids[j]);
  
  	              if (sound && sound._node) {
  	                sound._node.volume = sound._volume * vol;
  	              }
  	            }
  	          }
  	        }
  
  	        return self;
  	      }
  
  	      return self._volume;
  	    },
  
  	    /**
  	     * Handle muting and unmuting globally.
  	     * @param  {Boolean} muted Is muted or not.
  	     */
  	    mute: function(muted) {
  	      var self = this || Howler;
  
  	      // If we don't have an AudioContext created yet, run the setup.
  	      if (!self.ctx) {
  	        setupAudioContext();
  	      }
  
  	      self._muted = muted;
  
  	      // With Web Audio, we just need to mute the master gain.
  	      if (self.usingWebAudio) {
  	        self.masterGain.gain.value = muted ? 0 : self._volume;
  	      }
  
  	      // Loop through and mute all HTML5 Audio nodes.
  	      for (var i=0; i<self._howls.length; i++) {
  	        if (!self._howls[i]._webAudio) {
  	          // Get all of the sounds in this Howl group.
  	          var ids = self._howls[i]._getSoundIds();
  
  	          // Loop through all sounds and mark the audio node as muted.
  	          for (var j=0; j<ids.length; j++) {
  	            var sound = self._howls[i]._soundById(ids[j]);
  
  	            if (sound && sound._node) {
  	              sound._node.muted = (muted) ? true : sound._muted;
  	            }
  	          }
  	        }
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Unload and destroy all currently loaded Howl objects.
  	     * @return {Howler}
  	     */
  	    unload: function() {
  	      var self = this || Howler;
  
  	      for (var i=self._howls.length-1; i>=0; i--) {
  	        self._howls[i].unload();
  	      }
  
  	      // Create a new AudioContext to make sure it is fully reset.
  	      if (self.usingWebAudio && self.ctx && typeof self.ctx.close !== 'undefined') {
  	        self.ctx.close();
  	        self.ctx = null;
  	        setupAudioContext();
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Check for codec support of specific extension.
  	     * @param  {String} ext Audio file extention.
  	     * @return {Boolean}
  	     */
  	    codecs: function(ext) {
  	      return (this || Howler)._codecs[ext.replace(/^x-/, '')];
  	    },
  
  	    /**
  	     * Setup various state values for global tracking.
  	     * @return {Howler}
  	     */
  	    _setup: function() {
  	      var self = this || Howler;
  
  	      // Keeps track of the suspend/resume state of the AudioContext.
  	      self.state = self.ctx ? self.ctx.state || 'running' : 'running';
  
  	      // Automatically begin the 30-second suspend process
  	      self._autoSuspend();
  
  	      // Check if audio is available.
  	      if (!self.usingWebAudio) {
  	        // No audio is available on this system if noAudio is set to true.
  	        if (typeof Audio !== 'undefined') {
  	          try {
  	            var test = new Audio();
  
  	            // Check if the canplaythrough event is available.
  	            if (typeof test.oncanplaythrough === 'undefined') {
  	              self._canPlayEvent = 'canplay';
  	            }
  	          } catch(e) {
  	            self.noAudio = true;
  	          }
  	        } else {
  	          self.noAudio = true;
  	        }
  	      }
  
  	      // Test to make sure audio isn't disabled in Internet Explorer.
  	      try {
  	        var test = new Audio();
  	        if (test.muted) {
  	          self.noAudio = true;
  	        }
  	      } catch (e) {}
  
  	      // Check for supported codecs.
  	      if (!self.noAudio) {
  	        self._setupCodecs();
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Check for browser support for various codecs and cache the results.
  	     * @return {Howler}
  	     */
  	    _setupCodecs: function() {
  	      var self = this || Howler;
  	      var audioTest = null;
  
  	      // Must wrap in a try/catch because IE11 in server mode throws an error.
  	      try {
  	        audioTest = (typeof Audio !== 'undefined') ? new Audio() : null;
  	      } catch (err) {
  	        return self;
  	      }
  
  	      if (!audioTest || typeof audioTest.canPlayType !== 'function') {
  	        return self;
  	      }
  
  	      var mpegTest = audioTest.canPlayType('audio/mpeg;').replace(/^no$/, '');
  
  	      // Opera version <33 has mixed MP3 support, so we need to check for and block it.
  	      var checkOpera = self._navigator && self._navigator.userAgent.match(/OPR\/([0-6].)/g);
  	      var isOldOpera = (checkOpera && parseInt(checkOpera[0].split('/')[1], 10) < 33);
  
  	      self._codecs = {
  	        mp3: !!(!isOldOpera && (mpegTest || audioTest.canPlayType('audio/mp3;').replace(/^no$/, ''))),
  	        mpeg: !!mpegTest,
  	        opus: !!audioTest.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/, ''),
  	        ogg: !!audioTest.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, ''),
  	        oga: !!audioTest.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, ''),
  	        wav: !!audioTest.canPlayType('audio/wav; codecs="1"').replace(/^no$/, ''),
  	        aac: !!audioTest.canPlayType('audio/aac;').replace(/^no$/, ''),
  	        caf: !!audioTest.canPlayType('audio/x-caf;').replace(/^no$/, ''),
  	        m4a: !!(audioTest.canPlayType('audio/x-m4a;') || audioTest.canPlayType('audio/m4a;') || audioTest.canPlayType('audio/aac;')).replace(/^no$/, ''),
  	        mp4: !!(audioTest.canPlayType('audio/x-mp4;') || audioTest.canPlayType('audio/mp4;') || audioTest.canPlayType('audio/aac;')).replace(/^no$/, ''),
  	        weba: !!audioTest.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/, ''),
  	        webm: !!audioTest.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/, ''),
  	        dolby: !!audioTest.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/, ''),
  	        flac: !!(audioTest.canPlayType('audio/x-flac;') || audioTest.canPlayType('audio/flac;')).replace(/^no$/, '')
  	      };
  
  	      return self;
  	    },
  
  	    /**
  	     * Mobile browsers will only allow audio to be played after a user interaction.
  	     * Attempt to automatically unlock audio on the first user interaction.
  	     * Concept from: http://paulbakaus.com/tutorials/html5/web-audio-on-ios/
  	     * @return {Howler}
  	     */
  	    _enableMobileAudio: function() {
  	      var self = this || Howler;
  
  	      // Only run this on mobile devices if audio isn't already eanbled.
  	      var isMobile = /iPhone|iPad|iPod|Android|BlackBerry|BB10|Silk|Mobi/i.test(self._navigator && self._navigator.userAgent);
  	      var isTouch = !!(('ontouchend' in window) || (self._navigator && self._navigator.maxTouchPoints > 0) || (self._navigator && self._navigator.msMaxTouchPoints > 0));
  	      if (self._mobileEnabled || !self.ctx || (!isMobile && !isTouch)) {
  	        return;
  	      }
  
  	      self._mobileEnabled = false;
  
  	      // Some mobile devices/platforms have distortion issues when opening/closing tabs and/or web views.
  	      // Bugs in the browser (especially Mobile Safari) can cause the sampleRate to change from 44100 to 48000.
  	      // By calling Howler.unload(), we create a new AudioContext with the correct sampleRate.
  	      if (!self._mobileUnloaded && self.ctx.sampleRate !== 44100) {
  	        self._mobileUnloaded = true;
  	        self.unload();
  	      }
  
  	      // Scratch buffer for enabling iOS to dispose of web audio buffers correctly, as per:
  	      // http://stackoverflow.com/questions/24119684
  	      self._scratchBuffer = self.ctx.createBuffer(1, 1, 22050);
  
  	      // Call this method on touch start to create and play a buffer,
  	      // then check if the audio actually played to determine if
  	      // audio has now been unlocked on iOS, Android, etc.
  	      var unlock = function() {
  	        // Create an empty buffer.
  	        var source = self.ctx.createBufferSource();
  	        source.buffer = self._scratchBuffer;
  	        source.connect(self.ctx.destination);
  
  	        // Play the empty buffer.
  	        if (typeof source.start === 'undefined') {
  	          source.noteOn(0);
  	        } else {
  	          source.start(0);
  	        }
  
  	        // Setup a timeout to check that we are unlocked on the next event loop.
  	        source.onended = function() {
  	          source.disconnect(0);
  
  	          // Update the unlocked state and prevent this check from happening again.
  	          self._mobileEnabled = true;
  	          self.mobileAutoEnable = false;
  
  	          // Remove the touch start listener.
  	          document.removeEventListener('touchend', unlock, true);
  	        };
  	      };
  
  	      // Setup a touch start listener to attempt an unlock in.
  	      document.addEventListener('touchend', unlock, true);
  
  	      return self;
  	    },
  
  	    /**
  	     * Automatically suspend the Web Audio AudioContext after no sound has played for 30 seconds.
  	     * This saves processing/energy and fixes various browser-specific bugs with audio getting stuck.
  	     * @return {Howler}
  	     */
  	    _autoSuspend: function() {
  	      var self = this;
  
  	      if (!self.autoSuspend || !self.ctx || typeof self.ctx.suspend === 'undefined' || !Howler.usingWebAudio) {
  	        return;
  	      }
  
  	      // Check if any sounds are playing.
  	      for (var i=0; i<self._howls.length; i++) {
  	        if (self._howls[i]._webAudio) {
  	          for (var j=0; j<self._howls[i]._sounds.length; j++) {
  	            if (!self._howls[i]._sounds[j]._paused) {
  	              return self;
  	            }
  	          }
  	        }
  	      }
  
  	      if (self._suspendTimer) {
  	        clearTimeout(self._suspendTimer);
  	      }
  
  	      // If no sound has played after 30 seconds, suspend the context.
  	      self._suspendTimer = setTimeout(function() {
  	        if (!self.autoSuspend) {
  	          return;
  	        }
  
  	        self._suspendTimer = null;
  	        self.state = 'suspending';
  	        self.ctx.suspend().then(function() {
  	          self.state = 'suspended';
  
  	          if (self._resumeAfterSuspend) {
  	            delete self._resumeAfterSuspend;
  	            self._autoResume();
  	          }
  	        });
  	      }, 30000);
  
  	      return self;
  	    },
  
  	    /**
  	     * Automatically resume the Web Audio AudioContext when a new sound is played.
  	     * @return {Howler}
  	     */
  	    _autoResume: function() {
  	      var self = this;
  
  	      if (!self.ctx || typeof self.ctx.resume === 'undefined' || !Howler.usingWebAudio) {
  	        return;
  	      }
  
  	      if (self.state === 'running' && self._suspendTimer) {
  	        clearTimeout(self._suspendTimer);
  	        self._suspendTimer = null;
  	      } else if (self.state === 'suspended') {
  	        self.state = 'resuming';
  	        self.ctx.resume().then(function() {
  	          self.state = 'running';
  
  	          // Emit to all Howls that the audio has resumed.
  	          for (var i=0; i<self._howls.length; i++) {
  	            self._howls[i]._emit('resume');
  	          }
  	        });
  
  	        if (self._suspendTimer) {
  	          clearTimeout(self._suspendTimer);
  	          self._suspendTimer = null;
  	        }
  	      } else if (self.state === 'suspending') {
  	        self._resumeAfterSuspend = true;
  	      }
  
  	      return self;
  	    }
  	  };
  
  	  // Setup the global audio controller.
  	  var Howler = new HowlerGlobal();
  
  	  /** Group Methods **/
  	  /***************************************************************************/
  
  	  /**
  	   * Create an audio group controller.
  	   * @param {Object} o Passed in properties for this group.
  	   */
  	  var Howl = function(o) {
  	    var self = this;
  
  	    // Throw an error if no source is provided.
  	    if (!o.src || o.src.length === 0) {
  	      console.error('An array of source files must be passed with any new Howl.');
  	      return;
  	    }
  
  	    self.init(o);
  	  };
  	  Howl.prototype = {
  	    /**
  	     * Initialize a new Howl group object.
  	     * @param  {Object} o Passed in properties for this group.
  	     * @return {Howl}
  	     */
  	    init: function(o) {
  	      var self = this;
  
  	      // If we don't have an AudioContext created yet, run the setup.
  	      if (!Howler.ctx) {
  	        setupAudioContext();
  	      }
  
  	      // Setup user-defined default properties.
  	      self._autoplay = o.autoplay || false;
  	      self._format = (typeof o.format !== 'string') ? o.format : [o.format];
  	      self._html5 = o.html5 || false;
  	      self._muted = o.mute || false;
  	      self._loop = o.loop || false;
  	      self._pool = o.pool || 5;
  	      self._preload = (typeof o.preload === 'boolean') ? o.preload : true;
  	      self._rate = o.rate || 1;
  	      self._sprite = o.sprite || {};
  	      self._src = (typeof o.src !== 'string') ? o.src : [o.src];
  	      self._volume = o.volume !== undefined ? o.volume : 1;
  
  	      // Setup all other default properties.
  	      self._duration = 0;
  	      self._state = 'unloaded';
  	      self._sounds = [];
  	      self._endTimers = {};
  	      self._queue = [];
  
  	      // Setup event listeners.
  	      self._onend = o.onend ? [{fn: o.onend}] : [];
  	      self._onfade = o.onfade ? [{fn: o.onfade}] : [];
  	      self._onload = o.onload ? [{fn: o.onload}] : [];
  	      self._onloaderror = o.onloaderror ? [{fn: o.onloaderror}] : [];
  	      self._onpause = o.onpause ? [{fn: o.onpause}] : [];
  	      self._onplay = o.onplay ? [{fn: o.onplay}] : [];
  	      self._onstop = o.onstop ? [{fn: o.onstop}] : [];
  	      self._onmute = o.onmute ? [{fn: o.onmute}] : [];
  	      self._onvolume = o.onvolume ? [{fn: o.onvolume}] : [];
  	      self._onrate = o.onrate ? [{fn: o.onrate}] : [];
  	      self._onseek = o.onseek ? [{fn: o.onseek}] : [];
  	      self._onresume = [];
  
  	      // Web Audio or HTML5 Audio?
  	      self._webAudio = Howler.usingWebAudio && !self._html5;
  
  	      // Automatically try to enable audio on iOS.
  	      if (typeof Howler.ctx !== 'undefined' && Howler.ctx && Howler.mobileAutoEnable) {
  	        Howler._enableMobileAudio();
  	      }
  
  	      // Keep track of this Howl group in the global controller.
  	      Howler._howls.push(self);
  
  	      // If they selected autoplay, add a play event to the load queue.
  	      if (self._autoplay) {
  	        self._queue.push({
  	          event: 'play',
  	          action: function() {
  	            self.play();
  	          }
  	        });
  	      }
  
  	      // Load the source file unless otherwise specified.
  	      if (self._preload) {
  	        self.load();
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Load the audio file.
  	     * @return {Howler}
  	     */
  	    load: function() {
  	      var self = this;
  	      var url = null;
  
  	      // If no audio is available, quit immediately.
  	      if (Howler.noAudio) {
  	        self._emit('loaderror', null, 'No audio support.');
  	        return;
  	      }
  
  	      // Make sure our source is in an array.
  	      if (typeof self._src === 'string') {
  	        self._src = [self._src];
  	      }
  
  	      // Loop through the sources and pick the first one that is compatible.
  	      for (var i=0; i<self._src.length; i++) {
  	        var ext, str;
  
  	        if (self._format && self._format[i]) {
  	          // If an extension was specified, use that instead.
  	          ext = self._format[i];
  	        } else {
  	          // Make sure the source is a string.
  	          str = self._src[i];
  	          if (typeof str !== 'string') {
  	            self._emit('loaderror', null, 'Non-string found in selected audio sources - ignoring.');
  	            continue;
  	          }
  
  	          // Extract the file extension from the URL or base64 data URI.
  	          ext = /^data:audio\/([^;,]+);/i.exec(str);
  	          if (!ext) {
  	            ext = /\.([^.]+)$/.exec(str.split('?', 1)[0]);
  	          }
  
  	          if (ext) {
  	            ext = ext[1].toLowerCase();
  	          }
  	        }
  
  	        // Check if this extension is available.
  	        if (Howler.codecs(ext)) {
  	          url = self._src[i];
  	          break;
  	        }
  	      }
  
  	      if (!url) {
  	        self._emit('loaderror', null, 'No codec support for selected audio sources.');
  	        return;
  	      }
  
  	      self._src = url;
  	      self._state = 'loading';
  
  	      // If the hosting page is HTTPS and the source isn't,
  	      // drop down to HTML5 Audio to avoid Mixed Content errors.
  	      if (window.location.protocol === 'https:' && url.slice(0, 5) === 'http:') {
  	        self._html5 = true;
  	        self._webAudio = false;
  	      }
  
  	      // Create a new sound object and add it to the pool.
  	      new Sound(self);
  
  	      // Load and decode the audio data for playback.
  	      if (self._webAudio) {
  	        loadBuffer(self);
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Play a sound or resume previous playback.
  	     * @param  {String/Number} sprite   Sprite name for sprite playback or sound id to continue previous.
  	     * @param  {Boolean} internal Internal Use: true prevents event firing.
  	     * @return {Number}          Sound ID.
  	     */
  	    play: function(sprite, internal) {
  	      var self = this;
  	      var id = null;
  
  	      // Determine if a sprite, sound id or nothing was passed
  	      if (typeof sprite === 'number') {
  	        id = sprite;
  	        sprite = null;
  	      } else if (typeof sprite === 'string' && self._state === 'loaded' && !self._sprite[sprite]) {
  	        // If the passed sprite doesn't exist, do nothing.
  	        return null;
  	      } else if (typeof sprite === 'undefined') {
  	        // Use the default sound sprite (plays the full audio length).
  	        sprite = '__default';
  
  	        // Check if there is a single paused sound that isn't ended.
  	        // If there is, play that sound. If not, continue as usual.
  	        var num = 0;
  	        for (var i=0; i<self._sounds.length; i++) {
  	          if (self._sounds[i]._paused && !self._sounds[i]._ended) {
  	            num++;
  	            id = self._sounds[i]._id;
  	          }
  	        }
  
  	        if (num === 1) {
  	          sprite = null;
  	        } else {
  	          id = null;
  	        }
  	      }
  
  	      // Get the selected node, or get one from the pool.
  	      var sound = id ? self._soundById(id) : self._inactiveSound();
  
  	      // If the sound doesn't exist, do nothing.
  	      if (!sound) {
  	        return null;
  	      }
  
  	      // Select the sprite definition.
  	      if (id && !sprite) {
  	        sprite = sound._sprite || '__default';
  	      }
  
  	      // If we have no sprite and the sound hasn't loaded, we must wait
  	      // for the sound to load to get our audio's duration.
  	      if (self._state !== 'loaded' && !self._sprite[sprite]) {
  	        self._queue.push({
  	          event: 'play',
  	          action: function() {
  	            self.play(self._soundById(sound._id) ? sound._id : undefined);
  	          }
  	        });
  
  	        return sound._id;
  	      }
  
  	      // Don't play the sound if an id was passed and it is already playing.
  	      if (id && !sound._paused) {
  	        // Trigger the play event, in order to keep iterating through queue.
  	        if (!internal) {
  	          setTimeout(function() {
  	            self._emit('play', sound._id);
  	          }, 0);
  	        }
  
  	        return sound._id;
  	      }
  
  	      // Make sure the AudioContext isn't suspended, and resume it if it is.
  	      if (self._webAudio) {
  	        Howler._autoResume();
  	      }
  
  	      // Determine how long to play for and where to start playing.
  	      var seek = Math.max(0, sound._seek > 0 ? sound._seek : self._sprite[sprite][0] / 1000);
  	      var duration = Math.max(0, ((self._sprite[sprite][0] + self._sprite[sprite][1]) / 1000) - seek);
  	      var timeout = (duration * 1000) / Math.abs(sound._rate);
  
  	      // Update the parameters of the sound
  	      sound._paused = false;
  	      sound._ended = false;
  	      sound._sprite = sprite;
  	      sound._seek = seek;
  	      sound._start = self._sprite[sprite][0] / 1000;
  	      sound._stop = (self._sprite[sprite][0] + self._sprite[sprite][1]) / 1000;
  	      sound._loop = !!(sound._loop || self._sprite[sprite][2]);
  
  	      // Begin the actual playback.
  	      var node = sound._node;
  	      if (self._webAudio) {
  	        // Fire this when the sound is ready to play to begin Web Audio playback.
  	        var playWebAudio = function() {
  	          self._refreshBuffer(sound);
  
  	          // Setup the playback params.
  	          var vol = (sound._muted || self._muted) ? 0 : sound._volume;
  	          node.gain.setValueAtTime(vol, Howler.ctx.currentTime);
  	          sound._playStart = Howler.ctx.currentTime;
  
  	          // Play the sound using the supported method.
  	          if (typeof node.bufferSource.start === 'undefined') {
  	            sound._loop ? node.bufferSource.noteGrainOn(0, seek, 86400) : node.bufferSource.noteGrainOn(0, seek, duration);
  	          } else {
  	            sound._loop ? node.bufferSource.start(0, seek, 86400) : node.bufferSource.start(0, seek, duration);
  	          }
  
  	          // Start a new timer if none is present.
  	          if (timeout !== Infinity) {
  	            self._endTimers[sound._id] = setTimeout(self._ended.bind(self, sound), timeout);
  	          }
  
  	          if (!internal) {
  	            setTimeout(function() {
  	              self._emit('play', sound._id);
  	            }, 0);
  	          }
  	        };
  
  	        var isRunning = (Howler.state === 'running');
  	        if (self._state === 'loaded' && isRunning) {
  	          playWebAudio();
  	        } else {
  	          // Wait for the audio to load and then begin playback.
  	          self.once(isRunning ? 'load' : 'resume', playWebAudio, isRunning ? sound._id : null);
  
  	          // Cancel the end timer.
  	          self._clearTimer(sound._id);
  	        }
  	      } else {
  	        // Fire this when the sound is ready to play to begin HTML5 Audio playback.
  	        var playHtml5 = function() {
  	          node.currentTime = seek;
  	          node.muted = sound._muted || self._muted || Howler._muted || node.muted;
  	          node.volume = sound._volume * Howler.volume();
  	          node.playbackRate = sound._rate;
  
  	          setTimeout(function() {
  	            node.play();
  
  	            // Setup the new end timer.
  	            if (timeout !== Infinity) {
  	              self._endTimers[sound._id] = setTimeout(self._ended.bind(self, sound), timeout);
  	            }
  
  	            if (!internal) {
  	              self._emit('play', sound._id);
  	            }
  	          }, 0);
  	        };
  
  	        // Play immediately if ready, or wait for the 'canplaythrough'e vent.
  	        var loadedNoReadyState = (self._state === 'loaded' && (window && window.ejecta || !node.readyState && Howler._navigator.isCocoonJS));
  	        if (node.readyState === 4 || loadedNoReadyState) {
  	          playHtml5();
  	        } else {
  	          var listener = function() {
  	            // Begin playback.
  	            playHtml5();
  
  	            // Clear this listener.
  	            node.removeEventListener(Howler._canPlayEvent, listener, false);
  	          };
  	          node.addEventListener(Howler._canPlayEvent, listener, false);
  
  	          // Cancel the end timer.
  	          self._clearTimer(sound._id);
  	        }
  	      }
  
  	      return sound._id;
  	    },
  
  	    /**
  	     * Pause playback and save current position.
  	     * @param  {Number} id The sound ID (empty to pause all in group).
  	     * @return {Howl}
  	     */
  	    pause: function(id) {
  	      var self = this;
  
  	      // If the sound hasn't loaded, add it to the load queue to pause when capable.
  	      if (self._state !== 'loaded') {
  	        self._queue.push({
  	          event: 'pause',
  	          action: function() {
  	            self.pause(id);
  	          }
  	        });
  
  	        return self;
  	      }
  
  	      // If no id is passed, get all ID's to be paused.
  	      var ids = self._getSoundIds(id);
  
  	      for (var i=0; i<ids.length; i++) {
  	        // Clear the end timer.
  	        self._clearTimer(ids[i]);
  
  	        // Get the sound.
  	        var sound = self._soundById(ids[i]);
  
  	        if (sound && !sound._paused) {
  	          // Reset the seek position.
  	          sound._seek = self.seek(ids[i]);
  	          sound._rateSeek = 0;
  	          sound._paused = true;
  
  	          // Stop currently running fades.
  	          self._stopFade(ids[i]);
  
  	          if (sound._node) {
  	            if (self._webAudio) {
  	              // make sure the sound has been created
  	              if (!sound._node.bufferSource) {
  	                return self;
  	              }
  
  	              if (typeof sound._node.bufferSource.stop === 'undefined') {
  	                sound._node.bufferSource.noteOff(0);
  	              } else {
  	                sound._node.bufferSource.stop(0);
  	              }
  
  	              // Clean up the buffer source.
  	              self._cleanBuffer(sound._node);
  	            } else if (!isNaN(sound._node.duration) || sound._node.duration === Infinity) {
  	              sound._node.pause();
  	            }
  	          }
  	        }
  
  	        // Fire the pause event, unless `true` is passed as the 2nd argument.
  	        if (!arguments[1]) {
  	          self._emit('pause', sound ? sound._id : null);
  	        }
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Stop playback and reset to start.
  	     * @param  {Number} id The sound ID (empty to stop all in group).
  	     * @param  {Boolean} internal Internal Use: true prevents event firing.
  	     * @return {Howl}
  	     */
  	    stop: function(id, internal) {
  	      var self = this;
  
  	      // If the sound hasn't loaded, add it to the load queue to stop when capable.
  	      if (self._state !== 'loaded') {
  	        self._queue.push({
  	          event: 'stop',
  	          action: function() {
  	            self.stop(id);
  	          }
  	        });
  
  	        return self;
  	      }
  
  	      // If no id is passed, get all ID's to be stopped.
  	      var ids = self._getSoundIds(id);
  
  	      for (var i=0; i<ids.length; i++) {
  	        // Clear the end timer.
  	        self._clearTimer(ids[i]);
  
  	        // Get the sound.
  	        var sound = self._soundById(ids[i]);
  
  	        if (sound) {
  	          // Reset the seek position.
  	          sound._seek = sound._start || 0;
  	          sound._rateSeek = 0;
  	          sound._paused = true;
  	          sound._ended = true;
  
  	          // Stop currently running fades.
  	          self._stopFade(ids[i]);
  
  	          if (sound._node) {
  	            if (self._webAudio) {
  	              // make sure the sound has been created
  	              if (!sound._node.bufferSource) {
  	                if (!internal) {
  	                  self._emit('stop', sound._id);
  	                }
  
  	                return self;
  	              }
  
  	              if (typeof sound._node.bufferSource.stop === 'undefined') {
  	                sound._node.bufferSource.noteOff(0);
  	              } else {
  	                sound._node.bufferSource.stop(0);
  	              }
  
  	              // Clean up the buffer source.
  	              self._cleanBuffer(sound._node);
  	            } else if (!isNaN(sound._node.duration) || sound._node.duration === Infinity) {
  	              sound._node.currentTime = sound._start || 0;
  	              sound._node.pause();
  	            }
  	          }
  	        }
  
  	        if (sound && !internal) {
  	          self._emit('stop', sound._id);
  	        }
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Mute/unmute a single sound or all sounds in this Howl group.
  	     * @param  {Boolean} muted Set to true to mute and false to unmute.
  	     * @param  {Number} id    The sound ID to update (omit to mute/unmute all).
  	     * @return {Howl}
  	     */
  	    mute: function(muted, id) {
  	      var self = this;
  
  	      // If the sound hasn't loaded, add it to the load queue to mute when capable.
  	      if (self._state !== 'loaded') {
  	        self._queue.push({
  	          event: 'mute',
  	          action: function() {
  	            self.mute(muted, id);
  	          }
  	        });
  
  	        return self;
  	      }
  
  	      // If applying mute/unmute to all sounds, update the group's value.
  	      if (typeof id === 'undefined') {
  	        if (typeof muted === 'boolean') {
  	          self._muted = muted;
  	        } else {
  	          return self._muted;
  	        }
  	      }
  
  	      // If no id is passed, get all ID's to be muted.
  	      var ids = self._getSoundIds(id);
  
  	      for (var i=0; i<ids.length; i++) {
  	        // Get the sound.
  	        var sound = self._soundById(ids[i]);
  
  	        if (sound) {
  	          sound._muted = muted;
  
  	          if (self._webAudio && sound._node) {
  	            sound._node.gain.setValueAtTime(muted ? 0 : sound._volume, Howler.ctx.currentTime);
  	          } else if (sound._node) {
  	            sound._node.muted = Howler._muted ? true : muted;
  	          }
  
  	          self._emit('mute', sound._id);
  	        }
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Get/set the volume of this sound or of the Howl group. This method can optionally take 0, 1 or 2 arguments.
  	     *   volume() -> Returns the group's volume value.
  	     *   volume(id) -> Returns the sound id's current volume.
  	     *   volume(vol) -> Sets the volume of all sounds in this Howl group.
  	     *   volume(vol, id) -> Sets the volume of passed sound id.
  	     * @return {Howl/Number} Returns self or current volume.
  	     */
  	    volume: function() {
  	      var self = this;
  	      var args = arguments;
  	      var vol, id;
  
  	      // Determine the values based on arguments.
  	      if (args.length === 0) {
  	        // Return the value of the groups' volume.
  	        return self._volume;
  	      } else if (args.length === 1 || args.length === 2 && typeof args[1] === 'undefined') {
  	        // First check if this is an ID, and if not, assume it is a new volume.
  	        var ids = self._getSoundIds();
  	        var index = ids.indexOf(args[0]);
  	        if (index >= 0) {
  	          id = parseInt(args[0], 10);
  	        } else {
  	          vol = parseFloat(args[0]);
  	        }
  	      } else if (args.length >= 2) {
  	        vol = parseFloat(args[0]);
  	        id = parseInt(args[1], 10);
  	      }
  
  	      // Update the volume or return the current volume.
  	      var sound;
  	      if (typeof vol !== 'undefined' && vol >= 0 && vol <= 1) {
  	        // If the sound hasn't loaded, add it to the load queue to change volume when capable.
  	        if (self._state !== 'loaded') {
  	          self._queue.push({
  	            event: 'volume',
  	            action: function() {
  	              self.volume.apply(self, args);
  	            }
  	          });
  
  	          return self;
  	        }
  
  	        // Set the group volume.
  	        if (typeof id === 'undefined') {
  	          self._volume = vol;
  	        }
  
  	        // Update one or all volumes.
  	        id = self._getSoundIds(id);
  	        for (var i=0; i<id.length; i++) {
  	          // Get the sound.
  	          sound = self._soundById(id[i]);
  
  	          if (sound) {
  	            sound._volume = vol;
  
  	            // Stop currently running fades.
  	            if (!args[2]) {
  	              self._stopFade(id[i]);
  	            }
  
  	            if (self._webAudio && sound._node && !sound._muted) {
  	              sound._node.gain.setValueAtTime(vol, Howler.ctx.currentTime);
  	            } else if (sound._node && !sound._muted) {
  	              sound._node.volume = vol * Howler.volume();
  	            }
  
  	            self._emit('volume', sound._id);
  	          }
  	        }
  	      } else {
  	        sound = id ? self._soundById(id) : self._sounds[0];
  	        return sound ? sound._volume : 0;
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Fade a currently playing sound between two volumes (if no id is passsed, all sounds will fade).
  	     * @param  {Number} from The value to fade from (0.0 to 1.0).
  	     * @param  {Number} to   The volume to fade to (0.0 to 1.0).
  	     * @param  {Number} len  Time in milliseconds to fade.
  	     * @param  {Number} id   The sound id (omit to fade all sounds).
  	     * @return {Howl}
  	     */
  	    fade: function(from, to, len, id) {
  	      var self = this;
  	      var diff = Math.abs(from - to);
  	      var dir = from > to ? 'out' : 'in';
  	      var steps = diff / 0.01;
  	      var stepLen = (steps > 0) ? len / steps : len;
  
  	      // Since browsers clamp timeouts to 4ms, we need to clamp our steps to that too.
  	      if (stepLen < 4) {
  	        steps = Math.ceil(steps / (4 / stepLen));
  	        stepLen = 4;
  	      }
  
  	      // If the sound hasn't loaded, add it to the load queue to fade when capable.
  	      if (self._state !== 'loaded') {
  	        self._queue.push({
  	          event: 'fade',
  	          action: function() {
  	            self.fade(from, to, len, id);
  	          }
  	        });
  
  	        return self;
  	      }
  
  	      // Set the volume to the start position.
  	      self.volume(from, id);
  
  	      // Fade the volume of one or all sounds.
  	      var ids = self._getSoundIds(id);
  	      for (var i=0; i<ids.length; i++) {
  	        // Get the sound.
  	        var sound = self._soundById(ids[i]);
  
  	        // Create a linear fade or fall back to timeouts with HTML5 Audio.
  	        if (sound) {
  	          // Stop the previous fade if no sprite is being used (otherwise, volume handles this).
  	          if (!id) {
  	            self._stopFade(ids[i]);
  	          }
  
  	          // If we are using Web Audio, let the native methods do the actual fade.
  	          if (self._webAudio && !sound._muted) {
  	            var currentTime = Howler.ctx.currentTime;
  	            var end = currentTime + (len / 1000);
  	            sound._volume = from;
  	            sound._node.gain.setValueAtTime(from, currentTime);
  	            sound._node.gain.linearRampToValueAtTime(to, end);
  	          }
  
  	          var vol = from;
  	          sound._interval = setInterval(function(soundId, sound) {
  	            // Update the volume amount, but only if the volume should change.
  	            if (steps > 0) {
  	              vol += (dir === 'in' ? 0.01 : -0.01);
  	            }
  
  	            // Make sure the volume is in the right bounds.
  	            vol = Math.max(0, vol);
  	            vol = Math.min(1, vol);
  
  	            // Round to within 2 decimal points.
  	            vol = Math.round(vol * 100) / 100;
  
  	            // Change the volume.
  	            if (self._webAudio) {
  	              if (typeof id === 'undefined') {
  	                self._volume = vol;
  	              }
  
  	              sound._volume = vol;
  	            } else {
  	              self.volume(vol, soundId, true);
  	            }
  
  	            // When the fade is complete, stop it and fire event.
  	            if (vol === to) {
  	              clearInterval(sound._interval);
  	              sound._interval = null;
  	              self.volume(vol, soundId);
  	              self._emit('fade', soundId);
  	            }
  	          }.bind(self, ids[i], sound), stepLen);
  	        }
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Internal method that stops the currently playing fade when
  	     * a new fade starts, volume is changed or the sound is stopped.
  	     * @param  {Number} id The sound id.
  	     * @return {Howl}
  	     */
  	    _stopFade: function(id) {
  	      var self = this;
  	      var sound = self._soundById(id);
  
  	      if (sound && sound._interval) {
  	        if (self._webAudio) {
  	          sound._node.gain.cancelScheduledValues(Howler.ctx.currentTime);
  	        }
  
  	        clearInterval(sound._interval);
  	        sound._interval = null;
  	        self._emit('fade', id);
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Get/set the loop parameter on a sound. This method can optionally take 0, 1 or 2 arguments.
  	     *   loop() -> Returns the group's loop value.
  	     *   loop(id) -> Returns the sound id's loop value.
  	     *   loop(loop) -> Sets the loop value for all sounds in this Howl group.
  	     *   loop(loop, id) -> Sets the loop value of passed sound id.
  	     * @return {Howl/Boolean} Returns self or current loop value.
  	     */
  	    loop: function() {
  	      var self = this;
  	      var args = arguments;
  	      var loop, id, sound;
  
  	      // Determine the values for loop and id.
  	      if (args.length === 0) {
  	        // Return the grou's loop value.
  	        return self._loop;
  	      } else if (args.length === 1) {
  	        if (typeof args[0] === 'boolean') {
  	          loop = args[0];
  	          self._loop = loop;
  	        } else {
  	          // Return this sound's loop value.
  	          sound = self._soundById(parseInt(args[0], 10));
  	          return sound ? sound._loop : false;
  	        }
  	      } else if (args.length === 2) {
  	        loop = args[0];
  	        id = parseInt(args[1], 10);
  	      }
  
  	      // If no id is passed, get all ID's to be looped.
  	      var ids = self._getSoundIds(id);
  	      for (var i=0; i<ids.length; i++) {
  	        sound = self._soundById(ids[i]);
  
  	        if (sound) {
  	          sound._loop = loop;
  	          if (self._webAudio && sound._node && sound._node.bufferSource) {
  	            sound._node.bufferSource.loop = loop;
  	            if (loop) {
  	              sound._node.bufferSource.loopStart = sound._start || 0;
  	              sound._node.bufferSource.loopEnd = sound._stop;
  	            }
  	          }
  	        }
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Get/set the playback rate of a sound. This method can optionally take 0, 1 or 2 arguments.
  	     *   rate() -> Returns the first sound node's current playback rate.
  	     *   rate(id) -> Returns the sound id's current playback rate.
  	     *   rate(rate) -> Sets the playback rate of all sounds in this Howl group.
  	     *   rate(rate, id) -> Sets the playback rate of passed sound id.
  	     * @return {Howl/Number} Returns self or the current playback rate.
  	     */
  	    rate: function() {
  	      var self = this;
  	      var args = arguments;
  	      var rate, id;
  
  	      // Determine the values based on arguments.
  	      if (args.length === 0) {
  	        // We will simply return the current rate of the first node.
  	        id = self._sounds[0]._id;
  	      } else if (args.length === 1) {
  	        // First check if this is an ID, and if not, assume it is a new rate value.
  	        var ids = self._getSoundIds();
  	        var index = ids.indexOf(args[0]);
  	        if (index >= 0) {
  	          id = parseInt(args[0], 10);
  	        } else {
  	          rate = parseFloat(args[0]);
  	        }
  	      } else if (args.length === 2) {
  	        rate = parseFloat(args[0]);
  	        id = parseInt(args[1], 10);
  	      }
  
  	      // Update the playback rate or return the current value.
  	      var sound;
  	      if (typeof rate === 'number') {
  	        // If the sound hasn't loaded, add it to the load queue to change playback rate when capable.
  	        if (self._state !== 'loaded') {
  	          self._queue.push({
  	            event: 'rate',
  	            action: function() {
  	              self.rate.apply(self, args);
  	            }
  	          });
  
  	          return self;
  	        }
  
  	        // Set the group rate.
  	        if (typeof id === 'undefined') {
  	          self._rate = rate;
  	        }
  
  	        // Update one or all volumes.
  	        id = self._getSoundIds(id);
  	        for (var i=0; i<id.length; i++) {
  	          // Get the sound.
  	          sound = self._soundById(id[i]);
  
  	          if (sound) {
  	            // Keep track of our position when the rate changed and update the playback
  	            // start position so we can properly adjust the seek position for time elapsed.
  	            sound._rateSeek = self.seek(id[i]);
  	            sound._playStart = self._webAudio ? Howler.ctx.currentTime : sound._playStart;
  	            sound._rate = rate;
  
  	            // Change the playback rate.
  	            if (self._webAudio && sound._node && sound._node.bufferSource) {
  	              sound._node.bufferSource.playbackRate.value = rate;
  	            } else if (sound._node) {
  	              sound._node.playbackRate = rate;
  	            }
  
  	            // Reset the timers.
  	            var seek = self.seek(id[i]);
  	            var duration = ((self._sprite[sound._sprite][0] + self._sprite[sound._sprite][1]) / 1000) - seek;
  	            var timeout = (duration * 1000) / Math.abs(sound._rate);
  
  	            // Start a new end timer if sound is already playing.
  	            if (self._endTimers[id[i]] || !sound._paused) {
  	              self._clearTimer(id[i]);
  	              self._endTimers[id[i]] = setTimeout(self._ended.bind(self, sound), timeout);
  	            }
  
  	            self._emit('rate', sound._id);
  	          }
  	        }
  	      } else {
  	        sound = self._soundById(id);
  	        return sound ? sound._rate : self._rate;
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Get/set the seek position of a sound. This method can optionally take 0, 1 or 2 arguments.
  	     *   seek() -> Returns the first sound node's current seek position.
  	     *   seek(id) -> Returns the sound id's current seek position.
  	     *   seek(seek) -> Sets the seek position of the first sound node.
  	     *   seek(seek, id) -> Sets the seek position of passed sound id.
  	     * @return {Howl/Number} Returns self or the current seek position.
  	     */
  	    seek: function() {
  	      var self = this;
  	      var args = arguments;
  	      var seek, id;
  
  	      // Determine the values based on arguments.
  	      if (args.length === 0) {
  	        // We will simply return the current position of the first node.
  	        id = self._sounds[0]._id;
  	      } else if (args.length === 1) {
  	        // First check if this is an ID, and if not, assume it is a new seek position.
  	        var ids = self._getSoundIds();
  	        var index = ids.indexOf(args[0]);
  	        if (index >= 0) {
  	          id = parseInt(args[0], 10);
  	        } else {
  	          id = self._sounds[0]._id;
  	          seek = parseFloat(args[0]);
  	        }
  	      } else if (args.length === 2) {
  	        seek = parseFloat(args[0]);
  	        id = parseInt(args[1], 10);
  	      }
  
  	      // If there is no ID, bail out.
  	      if (typeof id === 'undefined') {
  	        return self;
  	      }
  
  	      // If the sound hasn't loaded, add it to the load queue to seek when capable.
  	      if (self._state !== 'loaded') {
  	        self._queue.push({
  	          event: 'seek',
  	          action: function() {
  	            self.seek.apply(self, args);
  	          }
  	        });
  
  	        return self;
  	      }
  
  	      // Get the sound.
  	      var sound = self._soundById(id);
  
  	      if (sound) {
  	        if (typeof seek === 'number' && seek >= 0) {
  	          // Pause the sound and update position for restarting playback.
  	          var playing = self.playing(id);
  	          if (playing) {
  	            self.pause(id, true);
  	          }
  
  	          // Move the position of the track and cancel timer.
  	          sound._seek = seek;
  	          sound._ended = false;
  	          self._clearTimer(id);
  
  	          // Restart the playback if the sound was playing.
  	          if (playing) {
  	            self.play(id, true);
  	          }
  
  	          // Update the seek position for HTML5 Audio.
  	          if (!self._webAudio && sound._node) {
  	            sound._node.currentTime = seek;
  	          }
  
  	          self._emit('seek', id);
  	        } else {
  	          if (self._webAudio) {
  	            var realTime = self.playing(id) ? Howler.ctx.currentTime - sound._playStart : 0;
  	            var rateSeek = sound._rateSeek ? sound._rateSeek - sound._seek : 0;
  	            return sound._seek + (rateSeek + realTime * Math.abs(sound._rate));
  	          } else {
  	            return sound._node.currentTime;
  	          }
  	        }
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Check if a specific sound is currently playing or not (if id is provided), or check if at least one of the sounds in the group is playing or not.
  	     * @param  {Number}  id The sound id to check. If none is passed, the whole sound group is checked.
  	     * @return {Boolean} True if playing and false if not.
  	     */
  	    playing: function(id) {
  	      var self = this;
  
  	      // Check the passed sound ID (if any).
  	      if (typeof id === 'number') {
  	        var sound = self._soundById(id);
  	        return sound ? !sound._paused : false;
  	      }
  
  	      // Otherwise, loop through all sounds and check if any are playing.
  	      for (var i=0; i<self._sounds.length; i++) {
  	        if (!self._sounds[i]._paused) {
  	          return true;
  	        }
  	      }
  
  	      return false;
  	    },
  
  	    /**
  	     * Get the duration of this sound. Passing a sound id will return the sprite duration.
  	     * @param  {Number} id The sound id to check. If none is passed, return full source duration.
  	     * @return {Number} Audio duration in seconds.
  	     */
  	    duration: function(id) {
  	      var self = this;
  	      var duration = self._duration;
  
  	      // If we pass an ID, get the sound and return the sprite length.
  	      var sound = self._soundById(id);
  	      if (sound) {
  	        duration = self._sprite[sound._sprite][1] / 1000;
  	      }
  
  	      return duration;
  	    },
  
  	    /**
  	     * Returns the current loaded state of this Howl.
  	     * @return {String} 'unloaded', 'loading', 'loaded'
  	     */
  	    state: function() {
  	      return this._state;
  	    },
  
  	    /**
  	     * Unload and destroy the current Howl object.
  	     * This will immediately stop all sound instances attached to this group.
  	     */
  	    unload: function() {
  	      var self = this;
  
  	      // Stop playing any active sounds.
  	      var sounds = self._sounds;
  	      for (var i=0; i<sounds.length; i++) {
  	        // Stop the sound if it is currently playing.
  	        if (!sounds[i]._paused) {
  	          self.stop(sounds[i]._id);
  	          self._emit('end', sounds[i]._id);
  	        }
  
  	        // Remove the source or disconnect.
  	        if (!self._webAudio) {
  	          // Set the source to 0-second silence to stop any downloading.
  	          sounds[i]._node.src = 'data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=';
  
  	          // Remove any event listeners.
  	          sounds[i]._node.removeEventListener('error', sounds[i]._errorFn, false);
  	          sounds[i]._node.removeEventListener(Howler._canPlayEvent, sounds[i]._loadFn, false);
  	        }
  
  	        // Empty out all of the nodes.
  	        delete sounds[i]._node;
  
  	        // Make sure all timers are cleared out.
  	        self._clearTimer(sounds[i]._id);
  
  	        // Remove the references in the global Howler object.
  	        var index = Howler._howls.indexOf(self);
  	        if (index >= 0) {
  	          Howler._howls.splice(index, 1);
  	        }
  	      }
  
  	      // Delete this sound from the cache (if no other Howl is using it).
  	      var remCache = true;
  	      for (i=0; i<Howler._howls.length; i++) {
  	        if (Howler._howls[i]._src === self._src) {
  	          remCache = false;
  	          break;
  	        }
  	      }
  
  	      if (cache && remCache) {
  	        delete cache[self._src];
  	      }
  
  	      // Clear global errors.
  	      Howler.noAudio = false;
  
  	      // Clear out `self`.
  	      self._state = 'unloaded';
  	      self._sounds = [];
  	      self = null;
  
  	      return null;
  	    },
  
  	    /**
  	     * Listen to a custom event.
  	     * @param  {String}   event Event name.
  	     * @param  {Function} fn    Listener to call.
  	     * @param  {Number}   id    (optional) Only listen to events for this sound.
  	     * @param  {Number}   once  (INTERNAL) Marks event to fire only once.
  	     * @return {Howl}
  	     */
  	    on: function(event, fn, id, once) {
  	      var self = this;
  	      var events = self['_on' + event];
  
  	      if (typeof fn === 'function') {
  	        events.push(once ? {id: id, fn: fn, once: once} : {id: id, fn: fn});
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Remove a custom event. Call without parameters to remove all events.
  	     * @param  {String}   event Event name.
  	     * @param  {Function} fn    Listener to remove. Leave empty to remove all.
  	     * @param  {Number}   id    (optional) Only remove events for this sound.
  	     * @return {Howl}
  	     */
  	    off: function(event, fn, id) {
  	      var self = this;
  	      var events = self['_on' + event];
  	      var i = 0;
  
  	      if (fn) {
  	        // Loop through event store and remove the passed function.
  	        for (i=0; i<events.length; i++) {
  	          if (fn === events[i].fn && id === events[i].id) {
  	            events.splice(i, 1);
  	            break;
  	          }
  	        }
  	      } else if (event) {
  	        // Clear out all events of this type.
  	        self['_on' + event] = [];
  	      } else {
  	        // Clear out all events of every type.
  	        var keys = Object.keys(self);
  	        for (i=0; i<keys.length; i++) {
  	          if ((keys[i].indexOf('_on') === 0) && Array.isArray(self[keys[i]])) {
  	            self[keys[i]] = [];
  	          }
  	        }
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Listen to a custom event and remove it once fired.
  	     * @param  {String}   event Event name.
  	     * @param  {Function} fn    Listener to call.
  	     * @param  {Number}   id    (optional) Only listen to events for this sound.
  	     * @return {Howl}
  	     */
  	    once: function(event, fn, id) {
  	      var self = this;
  
  	      // Setup the event listener.
  	      self.on(event, fn, id, 1);
  
  	      return self;
  	    },
  
  	    /**
  	     * Emit all events of a specific type and pass the sound id.
  	     * @param  {String} event Event name.
  	     * @param  {Number} id    Sound ID.
  	     * @param  {Number} msg   Message to go with event.
  	     * @return {Howl}
  	     */
  	    _emit: function(event, id, msg) {
  	      var self = this;
  	      var events = self['_on' + event];
  
  	      // Loop through event store and fire all functions.
  	      for (var i=events.length-1; i>=0; i--) {
  	        if (!events[i].id || events[i].id === id || event === 'load') {
  	          setTimeout(function(fn) {
  	            fn.call(this, id, msg);
  	          }.bind(self, events[i].fn), 0);
  
  	          // If this event was setup with `once`, remove it.
  	          if (events[i].once) {
  	            self.off(event, events[i].fn, events[i].id);
  	          }
  	        }
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Queue of actions initiated before the sound has loaded.
  	     * These will be called in sequence, with the next only firing
  	     * after the previous has finished executing (even if async like play).
  	     * @return {Howl}
  	     */
  	    _loadQueue: function() {
  	      var self = this;
  
  	      if (self._queue.length > 0) {
  	        var task = self._queue[0];
  
  	        // don't move onto the next task until this one is done
  	        self.once(task.event, function() {
  	          self._queue.shift();
  	          self._loadQueue();
  	        });
  
  	        task.action();
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Fired when playback ends at the end of the duration.
  	     * @param  {Sound} sound The sound object to work with.
  	     * @return {Howl}
  	     */
  	    _ended: function(sound) {
  	      var self = this;
  	      var sprite = sound._sprite;
  
  	      // Should this sound loop?
  	      var loop = !!(sound._loop || self._sprite[sprite][2]);
  
  	      // Fire the ended event.
  	      self._emit('end', sound._id);
  
  	      // Restart the playback for HTML5 Audio loop.
  	      if (!self._webAudio && loop) {
  	        self.stop(sound._id, true).play(sound._id);
  	      }
  
  	      // Restart this timer if on a Web Audio loop.
  	      if (self._webAudio && loop) {
  	        self._emit('play', sound._id);
  	        sound._seek = sound._start || 0;
  	        sound._rateSeek = 0;
  	        sound._playStart = Howler.ctx.currentTime;
  
  	        var timeout = ((sound._stop - sound._start) * 1000) / Math.abs(sound._rate);
  	        self._endTimers[sound._id] = setTimeout(self._ended.bind(self, sound), timeout);
  	      }
  
  	      // Mark the node as paused.
  	      if (self._webAudio && !loop) {
  	        sound._paused = true;
  	        sound._ended = true;
  	        sound._seek = sound._start || 0;
  	        sound._rateSeek = 0;
  	        self._clearTimer(sound._id);
  
  	        // Clean up the buffer source.
  	        self._cleanBuffer(sound._node);
  
  	        // Attempt to auto-suspend AudioContext if no sounds are still playing.
  	        Howler._autoSuspend();
  	      }
  
  	      // When using a sprite, end the track.
  	      if (!self._webAudio && !loop) {
  	        self.stop(sound._id);
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Clear the end timer for a sound playback.
  	     * @param  {Number} id The sound ID.
  	     * @return {Howl}
  	     */
  	    _clearTimer: function(id) {
  	      var self = this;
  
  	      if (self._endTimers[id]) {
  	        clearTimeout(self._endTimers[id]);
  	        delete self._endTimers[id];
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Return the sound identified by this ID, or return null.
  	     * @param  {Number} id Sound ID
  	     * @return {Object}    Sound object or null.
  	     */
  	    _soundById: function(id) {
  	      var self = this;
  
  	      // Loop through all sounds and find the one with this ID.
  	      for (var i=0; i<self._sounds.length; i++) {
  	        if (id === self._sounds[i]._id) {
  	          return self._sounds[i];
  	        }
  	      }
  
  	      return null;
  	    },
  
  	    /**
  	     * Return an inactive sound from the pool or create a new one.
  	     * @return {Sound} Sound playback object.
  	     */
  	    _inactiveSound: function() {
  	      var self = this;
  
  	      self._drain();
  
  	      // Find the first inactive node to recycle.
  	      for (var i=0; i<self._sounds.length; i++) {
  	        if (self._sounds[i]._ended) {
  	          return self._sounds[i].reset();
  	        }
  	      }
  
  	      // If no inactive node was found, create a new one.
  	      return new Sound(self);
  	    },
  
  	    /**
  	     * Drain excess inactive sounds from the pool.
  	     */
  	    _drain: function() {
  	      var self = this;
  	      var limit = self._pool;
  	      var cnt = 0;
  	      var i = 0;
  
  	      // If there are less sounds than the max pool size, we are done.
  	      if (self._sounds.length < limit) {
  	        return;
  	      }
  
  	      // Count the number of inactive sounds.
  	      for (i=0; i<self._sounds.length; i++) {
  	        if (self._sounds[i]._ended) {
  	          cnt++;
  	        }
  	      }
  
  	      // Remove excess inactive sounds, going in reverse order.
  	      for (i=self._sounds.length - 1; i>=0; i--) {
  	        if (cnt <= limit) {
  	          return;
  	        }
  
  	        if (self._sounds[i]._ended) {
  	          // Disconnect the audio source when using Web Audio.
  	          if (self._webAudio && self._sounds[i]._node) {
  	            self._sounds[i]._node.disconnect(0);
  	          }
  
  	          // Remove sounds until we have the pool size.
  	          self._sounds.splice(i, 1);
  	          cnt--;
  	        }
  	      }
  	    },
  
  	    /**
  	     * Get all ID's from the sounds pool.
  	     * @param  {Number} id Only return one ID if one is passed.
  	     * @return {Array}    Array of IDs.
  	     */
  	    _getSoundIds: function(id) {
  	      var self = this;
  
  	      if (typeof id === 'undefined') {
  	        var ids = [];
  	        for (var i=0; i<self._sounds.length; i++) {
  	          ids.push(self._sounds[i]._id);
  	        }
  
  	        return ids;
  	      } else {
  	        return [id];
  	      }
  	    },
  
  	    /**
  	     * Load the sound back into the buffer source.
  	     * @param  {Sound} sound The sound object to work with.
  	     * @return {Howl}
  	     */
  	    _refreshBuffer: function(sound) {
  	      var self = this;
  
  	      // Setup the buffer source for playback.
  	      sound._node.bufferSource = Howler.ctx.createBufferSource();
  	      sound._node.bufferSource.buffer = cache[self._src];
  
  	      // Connect to the correct node.
  	      if (sound._panner) {
  	        sound._node.bufferSource.connect(sound._panner);
  	      } else {
  	        sound._node.bufferSource.connect(sound._node);
  	      }
  
  	      // Setup looping and playback rate.
  	      sound._node.bufferSource.loop = sound._loop;
  	      if (sound._loop) {
  	        sound._node.bufferSource.loopStart = sound._start || 0;
  	        sound._node.bufferSource.loopEnd = sound._stop;
  	      }
  	      sound._node.bufferSource.playbackRate.value = sound._rate;
  
  	      return self;
  	    },
  
  	    /**
  	     * Prevent memory leaks by cleaning up the buffer source after playback.
  	     * @param  {Object} node Sound's audio node containing the buffer source.
  	     * @return {Howl}
  	     */
  	    _cleanBuffer: function(node) {
  	      var self = this;
  
  	      if (self._scratchBuffer) {
  	        node.bufferSource.onended = null;
  	        node.bufferSource.disconnect(0);
  	        try { node.bufferSource.buffer = self._scratchBuffer; } catch(e) {}
  	      }
  	      node.bufferSource = null;
  
  	      return self;
  	    }
  	  };
  
  	  /** Single Sound Methods **/
  	  /***************************************************************************/
  
  	  /**
  	   * Setup the sound object, which each node attached to a Howl group is contained in.
  	   * @param {Object} howl The Howl parent group.
  	   */
  	  var Sound = function(howl) {
  	    this._parent = howl;
  	    this.init();
  	  };
  	  Sound.prototype = {
  	    /**
  	     * Initialize a new Sound object.
  	     * @return {Sound}
  	     */
  	    init: function() {
  	      var self = this;
  	      var parent = self._parent;
  
  	      // Setup the default parameters.
  	      self._muted = parent._muted;
  	      self._loop = parent._loop;
  	      self._volume = parent._volume;
  	      self._muted = parent._muted;
  	      self._rate = parent._rate;
  	      self._seek = 0;
  	      self._paused = true;
  	      self._ended = true;
  	      self._sprite = '__default';
  
  	      // Generate a unique ID for this sound.
  	      self._id = Math.round(Date.now() * Math.random());
  
  	      // Add itself to the parent's pool.
  	      parent._sounds.push(self);
  
  	      // Create the new node.
  	      self.create();
  
  	      return self;
  	    },
  
  	    /**
  	     * Create and setup a new sound object, whether HTML5 Audio or Web Audio.
  	     * @return {Sound}
  	     */
  	    create: function() {
  	      var self = this;
  	      var parent = self._parent;
  	      var volume = (Howler._muted || self._muted || self._parent._muted) ? 0 : self._volume;
  
  	      if (parent._webAudio) {
  	        // Create the gain node for controlling volume (the source will connect to this).
  	        self._node = (typeof Howler.ctx.createGain === 'undefined') ? Howler.ctx.createGainNode() : Howler.ctx.createGain();
  	        self._node.gain.setValueAtTime(volume, Howler.ctx.currentTime);
  	        self._node.paused = true;
  	        self._node.connect(Howler.masterGain);
  	      } else {
  	        self._node = new Audio();
  
  	        // Listen for errors (http://dev.w3.org/html5/spec-author-view/spec.html#mediaerror).
  	        self._errorFn = self._errorListener.bind(self);
  	        self._node.addEventListener('error', self._errorFn, false);
  
  	        // Listen for 'canplaythrough' event to let us know the sound is ready.
  	        self._loadFn = self._loadListener.bind(self);
  	        self._node.addEventListener(Howler._canPlayEvent, self._loadFn, false);
  
  	        // Setup the new audio node.
  	        self._node.src = parent._src;
  	        self._node.preload = 'auto';
  	        self._node.volume = volume * Howler.volume();
  
  	        // Begin loading the source.
  	        self._node.load();
  	      }
  
  	      return self;
  	    },
  
  	    /**
  	     * Reset the parameters of this sound to the original state (for recycle).
  	     * @return {Sound}
  	     */
  	    reset: function() {
  	      var self = this;
  	      var parent = self._parent;
  
  	      // Reset all of the parameters of this sound.
  	      self._muted = parent._muted;
  	      self._loop = parent._loop;
  	      self._volume = parent._volume;
  	      self._muted = parent._muted;
  	      self._rate = parent._rate;
  	      self._seek = 0;
  	      self._rateSeek = 0;
  	      self._paused = true;
  	      self._ended = true;
  	      self._sprite = '__default';
  
  	      // Generate a new ID so that it isn't confused with the previous sound.
  	      self._id = Math.round(Date.now() * Math.random());
  
  	      return self;
  	    },
  
  	    /**
  	     * HTML5 Audio error listener callback.
  	     */
  	    _errorListener: function() {
  	      var self = this;
  
  	      // Fire an error event and pass back the code.
  	      self._parent._emit('loaderror', self._id, self._node.error ? self._node.error.code : 0);
  
  	      // Clear the event listener.
  	      self._node.removeEventListener('error', self._errorListener, false);
  	    },
  
  	    /**
  	     * HTML5 Audio canplaythrough listener callback.
  	     */
  	    _loadListener: function() {
  	      var self = this;
  	      var parent = self._parent;
  
  	      // Round up the duration to account for the lower precision in HTML5 Audio.
  	      parent._duration = Math.ceil(self._node.duration * 10) / 10;
  
  	      // Setup a sprite if none is defined.
  	      if (Object.keys(parent._sprite).length === 0) {
  	        parent._sprite = {__default: [0, parent._duration * 1000]};
  	      }
  
  	      if (parent._state !== 'loaded') {
  	        parent._state = 'loaded';
  	        parent._emit('load');
  	        parent._loadQueue();
  	      }
  
  	      // Clear the event listener.
  	      self._node.removeEventListener(Howler._canPlayEvent, self._loadFn, false);
  	    }
  	  };
  
  	  /** Helper Methods **/
  	  /***************************************************************************/
  
  	  var cache = {};
  
  	  /**
  	   * Buffer a sound from URL, Data URI or cache and decode to audio source (Web Audio API).
  	   * @param  {Howl} self
  	   */
  	  var loadBuffer = function(self) {
  	    var url = self._src;
  
  	    // Check if the buffer has already been cached and use it instead.
  	    if (cache[url]) {
  	      // Set the duration from the cache.
  	      self._duration = cache[url].duration;
  
  	      // Load the sound into this Howl.
  	      loadSound(self);
  
  	      return;
  	    }
  
  	    if (/^data:[^;]+;base64,/.test(url)) {
  	      // Decode the base64 data URI without XHR, since some browsers don't support it.
  	      var data = atob(url.split(',')[1]);
  	      var dataView = new Uint8Array(data.length);
  	      for (var i=0; i<data.length; ++i) {
  	        dataView[i] = data.charCodeAt(i);
  	      }
  
  	      decodeAudioData(dataView.buffer, self);
  	    } else {
  	      // Load the buffer from the URL.
  	      var xhr = new XMLHttpRequest();
  	      xhr.open('GET', url, true);
  	      xhr.responseType = 'arraybuffer';
  	      xhr.onload = function() {
  	        // Make sure we get a successful response back.
  	        var code = (xhr.status + '')[0];
  	        if (code !== '0' && code !== '2' && code !== '3') {
  	          self._emit('loaderror', null, 'Failed loading audio file with status: ' + xhr.status + '.');
  	          return;
  	        }
  
  	        decodeAudioData(xhr.response, self);
  	      };
  	      xhr.onerror = function() {
  	        // If there is an error, switch to HTML5 Audio.
  	        if (self._webAudio) {
  	          self._html5 = true;
  	          self._webAudio = false;
  	          self._sounds = [];
  	          delete cache[url];
  	          self.load();
  	        }
  	      };
  	      safeXhrSend(xhr);
  	    }
  	  };
  
  	  /**
  	   * Send the XHR request wrapped in a try/catch.
  	   * @param  {Object} xhr XHR to send.
  	   */
  	  var safeXhrSend = function(xhr) {
  	    try {
  	      xhr.send();
  	    } catch (e) {
  	      xhr.onerror();
  	    }
  	  };
  
  	  /**
  	   * Decode audio data from an array buffer.
  	   * @param  {ArrayBuffer} arraybuffer The audio data.
  	   * @param  {Howl}        self
  	   */
  	  var decodeAudioData = function(arraybuffer, self) {
  	    // Decode the buffer into an audio source.
  	    Howler.ctx.decodeAudioData(arraybuffer, function(buffer) {
  	      if (buffer && self._sounds.length > 0) {
  	        cache[self._src] = buffer;
  	        loadSound(self, buffer);
  	      }
  	    }, function() {
  	      self._emit('loaderror', null, 'Decoding audio data failed.');
  	    });
  	  };
  
  	  /**
  	   * Sound is now loaded, so finish setting everything up and fire the loaded event.
  	   * @param  {Howl} self
  	   * @param  {Object} buffer The decoded buffer sound source.
  	   */
  	  var loadSound = function(self, buffer) {
  	    // Set the duration.
  	    if (buffer && !self._duration) {
  	      self._duration = buffer.duration;
  	    }
  
  	    // Setup a sprite if none is defined.
  	    if (Object.keys(self._sprite).length === 0) {
  	      self._sprite = {__default: [0, self._duration * 1000]};
  	    }
  
  	    // Fire the loaded event.
  	    if (self._state !== 'loaded') {
  	      self._state = 'loaded';
  	      self._emit('load');
  	      self._loadQueue();
  	    }
  	  };
  
  	  /**
  	   * Setup the audio context when available, or switch to HTML5 Audio mode.
  	   */
  	  var setupAudioContext = function() {
  	    // Check if we are using Web Audio and setup the AudioContext if we are.
  	    try {
  	      if (typeof AudioContext !== 'undefined') {
  	        Howler.ctx = new AudioContext();
  	      } else if (typeof webkitAudioContext !== 'undefined') {
  	        Howler.ctx = new webkitAudioContext();
  	      } else {
  	        Howler.usingWebAudio = false;
  	      }
  	    } catch(e) {
  	      Howler.usingWebAudio = false;
  	    }
  
  	    // Check if a webview is being used on iOS8 or earlier (rather than the browser).
  	    // If it is, disable Web Audio as it causes crashing.
  	    var iOS = (/iP(hone|od|ad)/.test(Howler._navigator && Howler._navigator.platform));
  	    var appVersion = Howler._navigator && Howler._navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/);
  	    var version = appVersion ? parseInt(appVersion[1], 10) : null;
  	    if (iOS && version && version < 9) {
  	      var safari = /safari/.test(Howler._navigator && Howler._navigator.userAgent.toLowerCase());
  	      if (Howler._navigator && Howler._navigator.standalone && !safari || Howler._navigator && !Howler._navigator.standalone && !safari) {
  	        Howler.usingWebAudio = false;
  	      }
  	    }
  
  	    // Create and expose the master GainNode when using Web Audio (useful for plugins or advanced usage).
  	    if (Howler.usingWebAudio) {
  	      Howler.masterGain = (typeof Howler.ctx.createGain === 'undefined') ? Howler.ctx.createGainNode() : Howler.ctx.createGain();
  	      Howler.masterGain.gain.value = 1;
  	      Howler.masterGain.connect(Howler.ctx.destination);
  	    }
  
  	    // Re-run the setup on Howler.
  	    Howler._setup();
  	  };
  
  	  // Add support for AMD (Asynchronous Module Definition) libraries such as require.js.
  	  if (true) {
  	    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() {
  	      return {
  	        Howler: Howler,
  	        Howl: Howl
  	      };
  	    }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  	  }
  
  	  // Add support for CommonJS libraries such as browserify.
  	  if (true) {
  	    exports.Howler = Howler;
  	    exports.Howl = Howl;
  	  }
  
  	  // Define globally in case AMD is not available or unused.
  	  if (typeof window !== 'undefined') {
  	    window.HowlerGlobal = HowlerGlobal;
  	    window.Howler = Howler;
  	    window.Howl = Howl;
  	    window.Sound = Sound;
  	  } else if (typeof global !== 'undefined') { // Add to global in Node.js (for testing, etc).
  	    global.HowlerGlobal = HowlerGlobal;
  	    global.Howler = Howler;
  	    global.Howl = Howl;
  	    global.Sound = Sound;
  	  }
  	})();
  
  
  	/*!
  	 *  Spatial Plugin - Adds support for stereo and 3D audio where Web Audio is supported.
  	 *  
  	 *  howler.js v2.0.2
  	 *  howlerjs.com
  	 *
  	 *  (c) 2013-2016, James Simpson of GoldFire Studios
  	 *  goldfirestudios.com
  	 *
  	 *  MIT License
  	 */
  
  	(function() {
  
  	  'use strict';
  
  	  // Setup default properties.
  	  HowlerGlobal.prototype._pos = [0, 0, 0];
  	  HowlerGlobal.prototype._orientation = [0, 0, -1, 0, 1, 0];
  	  
  	  /** Global Methods **/
  	  /***************************************************************************/
  
  	  /**
  	   * Helper method to update the stereo panning position of all current Howls.
  	   * Future Howls will not use this value unless explicitly set.
  	   * @param  {Number} pan A value of -1.0 is all the way left and 1.0 is all the way right.
  	   * @return {Howler/Number}     Self or current stereo panning value.
  	   */
  	  HowlerGlobal.prototype.stereo = function(pan) {
  	    var self = this;
  
  	    // Stop right here if not using Web Audio.
  	    if (!self.ctx || !self.ctx.listener) {
  	      return self;
  	    }
  
  	    // Loop through all Howls and update their stereo panning.
  	    for (var i=self._howls.length-1; i>=0; i--) {
  	      self._howls[i].stereo(pan);
  	    }
  
  	    return self;
  	  };
  
  	  /**
  	   * Get/set the position of the listener in 3D cartesian space. Sounds using
  	   * 3D position will be relative to the listener's position.
  	   * @param  {Number} x The x-position of the listener.
  	   * @param  {Number} y The y-position of the listener.
  	   * @param  {Number} z The z-position of the listener.
  	   * @return {Howler/Array}   Self or current listener position.
  	   */
  	  HowlerGlobal.prototype.pos = function(x, y, z) {
  	    var self = this;
  
  	    // Stop right here if not using Web Audio.
  	    if (!self.ctx || !self.ctx.listener) {
  	      return self;
  	    }
  
  	    // Set the defaults for optional 'y' & 'z'.
  	    y = (typeof y !== 'number') ? self._pos[1] : y;
  	    z = (typeof z !== 'number') ? self._pos[2] : z;
  
  	    if (typeof x === 'number') {
  	      self._pos = [x, y, z];
  	      self.ctx.listener.setPosition(self._pos[0], self._pos[1], self._pos[2]);
  	    } else {
  	      return self._pos;
  	    }
  
  	    return self;
  	  };
  
  	  /**
  	   * Get/set the direction the listener is pointing in the 3D cartesian space.
  	   * A front and up vector must be provided. The front is the direction the
  	   * face of the listener is pointing, and up is the direction the top of the
  	   * listener is pointing. Thus, these values are expected to be at right angles
  	   * from each other.
  	   * @param  {Number} x   The x-orientation of the listener.
  	   * @param  {Number} y   The y-orientation of the listener.
  	   * @param  {Number} z   The z-orientation of the listener.
  	   * @param  {Number} xUp The x-orientation of the top of the listener.
  	   * @param  {Number} yUp The y-orientation of the top of the listener.
  	   * @param  {Number} zUp The z-orientation of the top of the listener.
  	   * @return {Howler/Array}     Returns self or the current orientation vectors.
  	   */
  	  HowlerGlobal.prototype.orientation = function(x, y, z, xUp, yUp, zUp) {
  	    var self = this;
  
  	    // Stop right here if not using Web Audio.
  	    if (!self.ctx || !self.ctx.listener) {
  	      return self;
  	    }
  
  	    // Set the defaults for optional 'y' & 'z'.
  	    var or = self._orientation;
  	    y = (typeof y !== 'number') ? or[1] : y;
  	    z = (typeof z !== 'number') ? or[2] : z;
  	    xUp = (typeof xUp !== 'number') ? or[3] : xUp;
  	    yUp = (typeof yUp !== 'number') ? or[4] : yUp;
  	    zUp = (typeof zUp !== 'number') ? or[5] : zUp;
  
  	    if (typeof x === 'number') {
  	      self._orientation = [x, y, z, xUp, yUp, zUp];
  	      self.ctx.listener.setOrientation(x, y, z, xUp, yUp, zUp);
  	    } else {
  	      return or;
  	    }
  
  	    return self;
  	  };
  
  	  /** Group Methods **/
  	  /***************************************************************************/
  
  	  /**
  	   * Add new properties to the core init.
  	   * @param  {Function} _super Core init method.
  	   * @return {Howl}
  	   */
  	  Howl.prototype.init = (function(_super) {
  	    return function(o) {
  	      var self = this;
  
  	      // Setup user-defined default properties.
  	      self._orientation = o.orientation || [1, 0, 0];
  	      self._stereo = o.stereo || null;
  	      self._pos = o.pos || null;
  	      self._pannerAttr = {
  	        coneInnerAngle: typeof o.coneInnerAngle !== 'undefined' ? o.coneInnerAngle : 360,
  	        coneOuterAngle: typeof o.coneOuterAngle !== 'undefined' ? o.coneOuterAngle : 360,
  	        coneOuterGain: typeof o.coneOuterGain !== 'undefined' ? o.coneOuterGain : 0,
  	        distanceModel: typeof o.distanceModel !== 'undefined' ? o.distanceModel : 'inverse',
  	        maxDistance: typeof o.maxDistance !== 'undefined' ? o.maxDistance : 10000,
  	        panningModel: typeof o.panningModel !== 'undefined' ? o.panningModel : 'HRTF',
  	        refDistance: typeof o.refDistance !== 'undefined' ? o.refDistance : 1,
  	        rolloffFactor: typeof o.rolloffFactor !== 'undefined' ? o.rolloffFactor : 1
  	      };
  
  	      // Setup event listeners.
  	      self._onstereo = o.onstereo ? [{fn: o.onstereo}] : [];
  	      self._onpos = o.onpos ? [{fn: o.onpos}] : [];
  	      self._onorientation = o.onorientation ? [{fn: o.onorientation}] : [];
  
  	      // Complete initilization with howler.js core's init function.
  	      return _super.call(this, o);
  	    };
  	  })(Howl.prototype.init);
  
  	  /**
  	   * Get/set the stereo panning of the audio source for this sound or all in the group.
  	   * @param  {Number} pan  A value of -1.0 is all the way left and 1.0 is all the way right.
  	   * @param  {Number} id (optional) The sound ID. If none is passed, all in group will be updated.
  	   * @return {Howl/Number}    Returns self or the current stereo panning value.
  	   */
  	  Howl.prototype.stereo = function(pan, id) {
  	    var self = this;
  
  	    // Stop right here if not using Web Audio.
  	    if (!self._webAudio) {
  	      return self;
  	    }
  
  	    // If the sound hasn't loaded, add it to the load queue to change stereo pan when capable.
  	    if (self._state !== 'loaded') {
  	      self._queue.push({
  	        event: 'stereo',
  	        action: function() {
  	          self.stereo(pan, id);
  	        }
  	      });
  
  	      return self;
  	    }
  
  	    // Check for PannerStereoNode support and fallback to PannerNode if it doesn't exist.
  	    var pannerType = (typeof Howler.ctx.createStereoPanner === 'undefined') ? 'spatial' : 'stereo';
  
  	    // Setup the group's stereo panning if no ID is passed.
  	    if (typeof id === 'undefined') {
  	      // Return the group's stereo panning if no parameters are passed.
  	      if (typeof pan === 'number') {
  	        self._stereo = pan;
  	        self._pos = [pan, 0, 0];
  	      } else {
  	        return self._stereo;
  	      }
  	    }
  
  	    // Change the streo panning of one or all sounds in group.
  	    var ids = self._getSoundIds(id);
  	    for (var i=0; i<ids.length; i++) {
  	      // Get the sound.
  	      var sound = self._soundById(ids[i]);
  
  	      if (sound) {
  	        if (typeof pan === 'number') {
  	          sound._stereo = pan;
  	          sound._pos = [pan, 0, 0];
  
  	          if (sound._node) {
  	            // If we are falling back, make sure the panningModel is equalpower.
  	            sound._pannerAttr.panningModel = 'equalpower';
  
  	            // Check if there is a panner setup and create a new one if not.
  	            if (!sound._panner || !sound._panner.pan) {
  	              setupPanner(sound, pannerType);
  	            }
  
  	            if (pannerType === 'spatial') {
  	              sound._panner.setPosition(pan, 0, 0);
  	            } else {
  	              sound._panner.pan.value = pan;
  	            }
  	          }
  
  	          self._emit('stereo', sound._id);
  	        } else {
  	          return sound._stereo;
  	        }
  	      }
  	    }
  
  	    return self;
  	  };
  
  	  /**
  	   * Get/set the 3D spatial position of the audio source for this sound or
  	   * all in the group. The most common usage is to set the 'x' position for
  	   * left/right panning. Setting any value higher than 1.0 will begin to
  	   * decrease the volume of the sound as it moves further away.
  	   * @param  {Number} x  The x-position of the audio from -1000.0 to 1000.0.
  	   * @param  {Number} y  The y-position of the audio from -1000.0 to 1000.0.
  	   * @param  {Number} z  The z-position of the audio from -1000.0 to 1000.0.
  	   * @param  {Number} id (optional) The sound ID. If none is passed, all in group will be updated.
  	   * @return {Howl/Array}    Returns self or the current 3D spatial position: [x, y, z].
  	   */
  	  Howl.prototype.pos = function(x, y, z, id) {
  	    var self = this;
  
  	    // Stop right here if not using Web Audio.
  	    if (!self._webAudio) {
  	      return self;
  	    }
  
  	    // If the sound hasn't loaded, add it to the load queue to change position when capable.
  	    if (self._state !== 'loaded') {
  	      self._queue.push({
  	        event: 'pos',
  	        action: function() {
  	          self.pos(x, y, z, id);
  	        }
  	      });
  
  	      return self;
  	    }
  
  	    // Set the defaults for optional 'y' & 'z'.
  	    y = (typeof y !== 'number') ? 0 : y;
  	    z = (typeof z !== 'number') ? -0.5 : z;
  
  	    // Setup the group's spatial position if no ID is passed.
  	    if (typeof id === 'undefined') {
  	      // Return the group's spatial position if no parameters are passed.
  	      if (typeof x === 'number') {
  	        self._pos = [x, y, z];
  	      } else {
  	        return self._pos;
  	      }
  	    }
  
  	    // Change the spatial position of one or all sounds in group.
  	    var ids = self._getSoundIds(id);
  	    for (var i=0; i<ids.length; i++) {
  	      // Get the sound.
  	      var sound = self._soundById(ids[i]);
  
  	      if (sound) {
  	        if (typeof x === 'number') {
  	          sound._pos = [x, y, z];
  
  	          if (sound._node) {
  	            // Check if there is a panner setup and create a new one if not.
  	            if (!sound._panner || sound._panner.pan) {
  	              setupPanner(sound, 'spatial');
  	            }
  
  	            sound._panner.setPosition(x, y, z);
  	          }
  
  	          self._emit('pos', sound._id);
  	        } else {
  	          return sound._pos;
  	        }
  	      }
  	    }
  
  	    return self;
  	  };
  
  	  /**
  	   * Get/set the direction the audio source is pointing in the 3D cartesian coordinate
  	   * space. Depending on how direction the sound is, based on the `cone` attributes,
  	   * a sound pointing away from the listener can be quiet or silent.
  	   * @param  {Number} x  The x-orientation of the source.
  	   * @param  {Number} y  The y-orientation of the source.
  	   * @param  {Number} z  The z-orientation of the source.
  	   * @param  {Number} id (optional) The sound ID. If none is passed, all in group will be updated.
  	   * @return {Howl/Array}    Returns self or the current 3D spatial orientation: [x, y, z].
  	   */
  	  Howl.prototype.orientation = function(x, y, z, id) {
  	    var self = this;
  
  	    // Stop right here if not using Web Audio.
  	    if (!self._webAudio) {
  	      return self;
  	    }
  
  	    // If the sound hasn't loaded, add it to the load queue to change orientation when capable.
  	    if (self._state !== 'loaded') {
  	      self._queue.push({
  	        event: 'orientation',
  	        action: function() {
  	          self.orientation(x, y, z, id);
  	        }
  	      });
  
  	      return self;
  	    }
  
  	    // Set the defaults for optional 'y' & 'z'.
  	    y = (typeof y !== 'number') ? self._orientation[1] : y;
  	    z = (typeof z !== 'number') ? self._orientation[2] : z;
  
  	    // Setup the group's spatial orientation if no ID is passed.
  	    if (typeof id === 'undefined') {
  	      // Return the group's spatial orientation if no parameters are passed.
  	      if (typeof x === 'number') {
  	        self._orientation = [x, y, z];
  	      } else {
  	        return self._orientation;
  	      }
  	    }
  
  	    // Change the spatial orientation of one or all sounds in group.
  	    var ids = self._getSoundIds(id);
  	    for (var i=0; i<ids.length; i++) {
  	      // Get the sound.
  	      var sound = self._soundById(ids[i]);
  
  	      if (sound) {
  	        if (typeof x === 'number') {
  	          sound._orientation = [x, y, z];
  
  	          if (sound._node) {
  	            // Check if there is a panner setup and create a new one if not.
  	            if (!sound._panner) {
  	              // Make sure we have a position to setup the node with.
  	              if (!sound._pos) {
  	                sound._pos = self._pos || [0, 0, -0.5];
  	              }
  
  	              setupPanner(sound, 'spatial');
  	            }
  
  	            sound._panner.setOrientation(x, y, z);
  	          }
  
  	          self._emit('orientation', sound._id);
  	        } else {
  	          return sound._orientation;
  	        }
  	      }
  	    }
  
  	    return self;
  	  };
  
  	  /**
  	   * Get/set the panner node's attributes for a sound or group of sounds.
  	   * This method can optionall take 0, 1 or 2 arguments.
  	   *   pannerAttr() -> Returns the group's values.
  	   *   pannerAttr(id) -> Returns the sound id's values.
  	   *   pannerAttr(o) -> Set's the values of all sounds in this Howl group.
  	   *   pannerAttr(o, id) -> Set's the values of passed sound id.
  	   *
  	   *   Attributes:
  	   *     coneInnerAngle - (360 by default) There will be no volume reduction inside this angle.
  	   *     coneOuterAngle - (360 by default) The volume will be reduced to a constant value of
  	   *                      `coneOuterGain` outside this angle.
  	   *     coneOuterGain - (0 by default) The amount of volume reduction outside of `coneOuterAngle`.
  	   *     distanceModel - ('inverse' by default) Determines algorithm to use to reduce volume as audio moves
  	   *                      away from listener. Can be `linear`, `inverse` or `exponential`.
  	   *     maxDistance - (10000 by default) Volume won't reduce between source/listener beyond this distance.
  	   *     panningModel - ('HRTF' by default) Determines which spatialization algorithm is used to position audio.
  	   *                     Can be `HRTF` or `equalpower`.
  	   *     refDistance - (1 by default) A reference distance for reducing volume as the source
  	   *                    moves away from the listener.
  	   *     rolloffFactor - (1 by default) How quickly the volume reduces as source moves from listener.
  	   * 
  	   * @return {Howl/Object} Returns self or current panner attributes.
  	   */
  	  Howl.prototype.pannerAttr = function() {
  	    var self = this;
  	    var args = arguments;
  	    var o, id, sound;
  
  	    // Stop right here if not using Web Audio.
  	    if (!self._webAudio) {
  	      return self;
  	    }
  
  	    // Determine the values based on arguments.
  	    if (args.length === 0) {
  	      // Return the group's panner attribute values.
  	      return self._pannerAttr;
  	    } else if (args.length === 1) {
  	      if (typeof args[0] === 'object') {
  	        o = args[0];
  
  	        // Set the grou's panner attribute values.
  	        if (typeof id === 'undefined') {
  	          self._pannerAttr = {
  	            coneInnerAngle: typeof o.coneInnerAngle !== 'undefined' ? o.coneInnerAngle : self._coneInnerAngle,
  	            coneOuterAngle: typeof o.coneOuterAngle !== 'undefined' ? o.coneOuterAngle : self._coneOuterAngle,
  	            coneOuterGain: typeof o.coneOuterGain !== 'undefined' ? o.coneOuterGain : self._coneOuterGain,
  	            distanceModel: typeof o.distanceModel !== 'undefined' ? o.distanceModel : self._distanceModel,
  	            maxDistance: typeof o.maxDistance !== 'undefined' ? o.maxDistance : self._maxDistance,
  	            panningModel: typeof o.panningModel !== 'undefined' ? o.panningModel : self._panningModel,
  	            refDistance: typeof o.refDistance !== 'undefined' ? o.refDistance : self._refDistance,
  	            rolloffFactor: typeof o.rolloffFactor !== 'undefined' ? o.rolloffFactor : self._rolloffFactor
  	          };
  	        }
  	      } else {
  	        // Return this sound's panner attribute values.
  	        sound = self._soundById(parseInt(args[0], 10));
  	        return sound ? sound._pannerAttr : self._pannerAttr;
  	      }
  	    } else if (args.length === 2) {
  	      o = args[0];
  	      id = parseInt(args[1], 10);
  	    }
  
  	    // Update the values of the specified sounds.
  	    var ids = self._getSoundIds(id);
  	    for (var i=0; i<ids.length; i++) {
  	      sound = self._soundById(ids[i]);
  
  	      if (sound) {
  	        // Merge the new values into the sound.
  	        var pa = sound._pannerAttr;
  	        pa = {
  	          coneInnerAngle: typeof o.coneInnerAngle !== 'undefined' ? o.coneInnerAngle : pa.coneInnerAngle,
  	          coneOuterAngle: typeof o.coneOuterAngle !== 'undefined' ? o.coneOuterAngle : pa.coneOuterAngle,
  	          coneOuterGain: typeof o.coneOuterGain !== 'undefined' ? o.coneOuterGain : pa.coneOuterGain,
  	          distanceModel: typeof o.distanceModel !== 'undefined' ? o.distanceModel : pa.distanceModel,
  	          maxDistance: typeof o.maxDistance !== 'undefined' ? o.maxDistance : pa.maxDistance,
  	          panningModel: typeof o.panningModel !== 'undefined' ? o.panningModel : pa.panningModel,
  	          refDistance: typeof o.refDistance !== 'undefined' ? o.refDistance : pa.refDistance,
  	          rolloffFactor: typeof o.rolloffFactor !== 'undefined' ? o.rolloffFactor : pa.rolloffFactor
  	        };
  
  	        // Update the panner values or create a new panner if none exists.
  	        var panner = sound._panner;
  	        if (panner) {
  	          panner.coneInnerAngle = pa.coneInnerAngle;
  	          panner.coneOuterAngle = pa.coneOuterAngle;
  	          panner.coneOuterGain = pa.coneOuterGain;
  	          panner.distanceModel = pa.distanceModel;
  	          panner.maxDistance = pa.maxDistance;
  	          panner.panningModel = pa.panningModel;
  	          panner.refDistance = pa.refDistance;
  	          panner.rolloffFactor = pa.rolloffFactor;
  	        } else {
  	          // Make sure we have a position to setup the node with.
  	          if (!sound._pos) {
  	            sound._pos = self._pos || [0, 0, -0.5];
  	          }
  
  	          // Create a new panner node.
  	          setupPanner(sound, 'spatial');
  	        }
  	      }
  	    }
  
  	    return self;
  	  };
  
  	  /** Single Sound Methods **/
  	  /***************************************************************************/
  
  	  /**
  	   * Add new properties to the core Sound init.
  	   * @param  {Function} _super Core Sound init method.
  	   * @return {Sound}
  	   */
  	  Sound.prototype.init = (function(_super) {
  	    return function() {
  	      var self = this;
  	      var parent = self._parent;
  
  	      // Setup user-defined default properties.
  	      self._orientation = parent._orientation;
  	      self._stereo = parent._stereo;
  	      self._pos = parent._pos;
  	      self._pannerAttr = parent._pannerAttr;
  
  	      // Complete initilization with howler.js core Sound's init function.
  	      _super.call(this);
  
  	      // If a stereo or position was specified, set it up.
  	      if (self._stereo) {
  	        parent.stereo(self._stereo);
  	      } else if (self._pos) {
  	        parent.pos(self._pos[0], self._pos[1], self._pos[2], self._id);
  	      }
  	    };
  	  })(Sound.prototype.init);
  
  	  /**
  	   * Override the Sound.reset method to clean up properties from the spatial plugin.
  	   * @param  {Function} _super Sound reset method.
  	   * @return {Sound}
  	   */
  	  Sound.prototype.reset = (function(_super) {
  	    return function() {
  	      var self = this;
  	      var parent = self._parent;
  
  	      // Reset all spatial plugin properties on this sound.
  	      self._orientation = parent._orientation;
  	      self._pos = parent._pos;
  	      self._pannerAttr = parent._pannerAttr;
  
  	      // Complete resetting of the sound.
  	      return _super.call(this);
  	    };
  	  })(Sound.prototype.reset);
  
  	  /** Helper Methods **/
  	  /***************************************************************************/
  
  	  /**
  	   * Create a new panner node and save it on the sound.
  	   * @param  {Sound} sound Specific sound to setup panning on.
  	   * @param {String} type Type of panner to create: 'stereo' or 'spatial'.
  	   */
  	  var setupPanner = function(sound, type) {
  	    type = type || 'spatial';
  
  	    // Create the new panner node.
  	    if (type === 'spatial') {
  	      sound._panner = Howler.ctx.createPanner();
  	      sound._panner.coneInnerAngle = sound._pannerAttr.coneInnerAngle;
  	      sound._panner.coneOuterAngle = sound._pannerAttr.coneOuterAngle;
  	      sound._panner.coneOuterGain = sound._pannerAttr.coneOuterGain;
  	      sound._panner.distanceModel = sound._pannerAttr.distanceModel;
  	      sound._panner.maxDistance = sound._pannerAttr.maxDistance;
  	      sound._panner.panningModel = sound._pannerAttr.panningModel;
  	      sound._panner.refDistance = sound._pannerAttr.refDistance;
  	      sound._panner.rolloffFactor = sound._pannerAttr.rolloffFactor;
  	      sound._panner.setPosition(sound._pos[0], sound._pos[1], sound._pos[2]);
  	      sound._panner.setOrientation(sound._orientation[0], sound._orientation[1], sound._orientation[2]);
  	    } else {
  	      sound._panner = Howler.ctx.createStereoPanner();
  	      sound._panner.pan.value = sound._stereo;
  	    }
  
  	    sound._panner.connect(sound._node);
  
  	    // Update the connections.
  	    if (!sound._paused) {
  	      sound._parent.pause(sound._id, true).play(sound._id);
  	    }
  	  };
  	})();
  
  	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  
  /***/ },
  /* 57 */
  /***/ function(module, exports) {
  
  	module.exports = "data:audio/mpeg;base64,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
  
  /***/ }
  /******/ ]);